<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <description>A personal blog about emotions and the human experience.</description>
    <item>
      <description>&lt;p&gt;There are multiple ways to deal with non-application dependencies (i.e. &amp;ldquo;tools&amp;rdquo; that your project needs).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;go-tool&#34;&gt;go tool&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of Go 1.24 (Feb 2025)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To add a new tool:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;go get -tool golang.org/x/lint/golint&#xA;go get -tool github.com/mgechev/revive@latest&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To run the tool:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;go tool golint -h&#xA;go tool golang.org/x/lint/golint -h # in case of naming overlap&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To see a list of all tools:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;go tool&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To update all tools:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;go get -u tool&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you check the &lt;code&gt;go.mod&lt;/code&gt; you&amp;rsquo;ll see a new tool syntax:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go.mod&#34;&gt;module testing-tools&#xA;&#xA;go 1.23.4&#xA;&#xA;tool (&#xA;    github.com/mgechev/revive&#xA;    golang.org/x/lint/golint&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;caveats-and-issues&#34;&gt;Caveats and Issues&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now, there is a problem (sort of), which is that you&amp;rsquo;ll see a bunch of &lt;em&gt;indirect&lt;/em&gt; dependencies showing up in the &lt;code&gt;go.mod&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because these are the dependencies that your &amp;ldquo;tools&amp;rdquo; need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m less concerned about that as a side-effect of using the new &lt;code&gt;go tools&lt;/code&gt; feature, but I appreciate it&amp;rsquo;s not ideal.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My concern being: it&amp;rsquo;s more mental overhead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t know if these &lt;em&gt;indirect&lt;/em&gt; dependencies are transient dependencies used by your application dependencies, or if they&amp;rsquo;re dependencies for the &amp;ldquo;tools&amp;rdquo; you&amp;rsquo;ve installed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I&amp;rsquo;m not usually &lt;em&gt;that fussed&lt;/em&gt; by this is because I only really care about the &amp;ldquo;direct&amp;rdquo; dependencies, and those are always clear because they don&amp;rsquo;t have &lt;code&gt;// indirect&lt;/code&gt; following them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;So the following instructions are only relevant if you really care about this&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;multiple-module-files&#34;&gt;Multiple Module Files&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is another option on the table that we can use, and it doesn&amp;rsquo;t appear to be too much additional maintenance or mental overhead, which is great. But it does have a downside (see the &lt;code&gt;IMPORTANT&lt;/code&gt; note at the end of this section).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Essentially, the approach is to have a separate modfile for tools.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It means we&amp;rsquo;d have multiple files now, like this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go.mod&#xA;go.sum&#xA;tools.mod&#xA;tools.sum&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;If you give the &lt;code&gt;tools.mod&lt;/code&gt; a unique module name, let&amp;rsquo;s say &lt;code&gt;go.mod&lt;/code&gt; uses &lt;code&gt;github.com/example/foo&lt;/code&gt;, and so you make &lt;code&gt;tools.mod&lt;/code&gt; use &lt;code&gt;github.com/example/foo/tools&lt;/code&gt; then be aware that the use of &lt;code&gt;go mod&lt;/code&gt; isn&amp;rsquo;t going to make your &lt;code&gt;tools.mod&lt;/code&gt; think it needs the module from &lt;code&gt;go.mod&lt;/code&gt; and it&amp;rsquo;ll add it as a dependency (this makes things weird in special cases), so it might be worth making the module name the same between &lt;code&gt;go.mod&lt;/code&gt; and &lt;code&gt;tools.mod&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To install a new tool:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# instead of...&#xA;go get -tool github.com/mgechev/revive&#xA;&#xA;# we do...&#xA;go get -modfile=tools.mod -tool github.com/mgechev/revive&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;To &lt;em&gt;remove&lt;/em&gt; a tool you can do the above but set the version to &lt;code&gt;@none&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;And if we want to use that tool we have to make sure to specify the modfile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ go tool revive --version&#xA;go: no such tool &amp;quot;revive&amp;quot;&#xA;&#xA;$ go tool -modfile=tools.mod revive --version&#xA;version 1.7.0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Having to specify the &lt;code&gt;-modfile&lt;/code&gt; flag isn&amp;rsquo;t a big issue as we already have &lt;code&gt;go tool&lt;/code&gt; abstracted inside the various Makefile targets, so we should only ever be calling a Makefile target (or in the case of stringer have it codified in the go generate directive in the code itself).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As far as updating tools, you can either do it a dependency at a time or all of them at once:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# instead of...&#xA;go get -u -tool github.com/mgechev/revive@latest&#xA;go get -u tool&#xA;&#xA;# we do...&#xA;go get -u -modfile=tools.mod -tool github.com/mgechev/revive@latest&#xA;go get -u -modfile=tools.mod tool&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Same for listing the installed tools:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# instead of...&#xA;go tool&#xA;&#xA;# we do...&#xA;go tool -modfile=tools.mod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;Can also try &lt;code&gt;go list -modfile=tools.mod tool&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To verify the integrity of the tool dependencies:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go mod verify -modfile=tools.mod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s an associated Makefile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-Makefile&#34;&gt;.PHONY: deps-app-update&#xA;deps-app-update: ## Update all application dependencies&#xA;    go get -u -t ./...&#xA;    go mod tidy&#xA;    if [ -d &amp;quot;vendor&amp;quot; ]; then go mod vendor; fi&#xA;    &#xA;.PHONY: deps-outdated&#xA;deps-outdated:  ## Lists direct dependencies that have a newer version available&#xA;    @go list -u -m -json all | go tool -modfile=tools.mod go-mod-outdated -update -direct&#xA;    &#xA;TOOLS = \&#xA;    cuelang.org/go/cmd/cue \&#xA;    github.com/client9/misspell/cmd/misspell \&#xA;    github.com/go-delve/delve/cmd/dlv \&#xA;    github.com/mgechev/revive \&#xA;    github.com/psampaz/go-mod-outdated \&#xA;    github.com/stealthrocket/wasi-go/cmd/wasirun \&#xA;    github.com/stern/stern \&#xA;    github.com/tetratelabs/wazero/cmd/wazero \&#xA;    golang.org/x/lint/golint \&#xA;    golang.org/x/tools/cmd/stringer \&#xA;    golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness \&#xA;    golang.org/x/vuln/cmd/govulncheck \&#xA;    honnef.co/go/tools/cmd/staticcheck \&#xA;    mvdan.cc/gofumpt \&#xA;&#xA;.PHONY: tools&#xA;tools:&#xA;    @$(foreach tool,$(TOOLS), \&#xA;        if ! go tool -modfile=tools.mod | grep &amp;quot;$(tool)&amp;quot; &amp;gt;/dev/null; then \&#xA;            go get -modfile=tools.mod -tool &amp;quot;$(tool)&amp;quot;@latest; \&#xA;        fi; \&#xA;    )&#xA;&#xA;.PHONY: tools-update&#xA;tools-update:&#xA;    go get -u -modfile=tools.mod tool&#xA;    go mod tidy -modfile=tools.mod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;This approach keeps the main &lt;code&gt;go.mod&lt;/code&gt; and &lt;code&gt;go.sum&lt;/code&gt; clean of any tool dependencies, but not the other way around. So the &lt;code&gt;tools.mod&lt;/code&gt; and &lt;code&gt;tools.sum&lt;/code&gt; will ultimately contain all the dependencies from the main &lt;code&gt;go.mod&lt;/code&gt; (that is a side-effect of running &lt;code&gt;go mod tidy -modfile=tools.mod&lt;/code&gt; as &lt;code&gt;go mod&lt;/code&gt; always consults the main &lt;code&gt;go.mod&lt;/code&gt;, hence all of its dependencies end up in your &lt;code&gt;tools.mod&lt;/code&gt; and &lt;code&gt;tools.sum&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is unavoidable. There is no way to get around it (trust me, I&amp;rsquo;ve tried 😅).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, this isn&amp;rsquo;t the end of the world as the &lt;code&gt;tools&lt;/code&gt; directive is still at the top of the &lt;code&gt;tools.mod&lt;/code&gt; and is very clear as to what &amp;ldquo;tools&amp;rdquo; are installed, but yeah, you&amp;rsquo;ll also see a bunch of &lt;code&gt;require&lt;/code&gt; directives (related to your main Go project) as well, unfortunately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing you could do, is only run the &lt;code&gt;go get -u -modfile=tools.mod tool&lt;/code&gt; command, which would keep your &lt;code&gt;tools.mod&lt;/code&gt; clean, and would only update &lt;code&gt;tools.sum&lt;/code&gt; with the relevant updated dependencies. The problem with that is the old dependencies aren&amp;rsquo;t cleaned out. e.g. if you updated tool &amp;ldquo;foo&amp;rdquo; from version 1.0 to 2.0 then both versions appear in your &lt;code&gt;tools.sum&lt;/code&gt; (this is why we have &lt;code&gt;go mod tidy&lt;/code&gt; to ensure only 2.0 is present in the &lt;code&gt;tools.sum&lt;/code&gt;). So one approach would simple be to manually clean up the &lt;code&gt;go.sum&lt;/code&gt; everytime after running &lt;code&gt;go get -u -modfile=tools.mod tool&lt;/code&gt; &amp;ndash; it&amp;rsquo;s not that difficult as you just look for the new tool version added and remove the old one, but it&amp;rsquo;s a manual process and that sucks).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;tools-go&#34;&gt;tools.go&lt;/h2&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;For more details on code generation in a general sense, refer to:&lt;br&gt;&#xA;&lt;a href=&#34;https://gist.github.com/Integralist/8f39eb897316e1cbeaf9eff8326cfa59&#34; target=&#34;_blank&#34;&gt;https://gist.github.com/Integralist/8f39eb897316e1cbeaf9eff8326cfa59&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The following file &lt;code&gt;internal/tools/tools.go&lt;/code&gt; uses a build tag to avoid the dependencies being compiled into your application binary&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;//go:build tools&#xA;&#xA;// Package tools manages go-based tools that are used to develop in this repo.&#xA;package tools&#xA;&#xA;import (&#xA;    _ &amp;quot;github.com/nbio/cart&amp;quot;&#xA;    _ &amp;quot;github.com/nbio/slugger&amp;quot;&#xA;    _ &amp;quot;github.com/psampaz/go-mod-outdated&amp;quot;&#xA;    _ &amp;quot;github.com/stealthrocket/wasi-go/cmd/wasirun&amp;quot;&#xA;    _ &amp;quot;github.com/tetratelabs/wazero/cmd/wazero&amp;quot;&#xA;    _ &amp;quot;golang.org/x/lint/golint&amp;quot;&#xA;    _ &amp;quot;golang.org/x/tools/cmd/stringer&amp;quot;&#xA;    _ &amp;quot;golang.org/x/vuln/cmd/govulncheck&amp;quot;&#xA;)&#xA;&#xA;//go:generate go install github.com/nbio/cart&#xA;//go:generate go install github.com/nbio/slugger&#xA;//go:generate go install github.com/psampaz/go-mod-outdated&#xA;//go:generate go install github.com/stealthrocket/wasi-go/cmd/wasirun&#xA;//go:generate go install github.com/tetratelabs/wazero/cmd/wazero&#xA;//go:generate go install golang.org/x/lint/golint&#xA;//go:generate go install golang.org/x/vuln/cmd/govulncheck&#xA;//go:generate go install golang.org/x/tools/cmd/stringer&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the &lt;code&gt;go:generate&lt;/code&gt; comments? Yup, we invoke them like so (notice the &lt;code&gt;-tags&lt;/code&gt; flag):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-Makefile&#34;&gt;tools: internal/tools/tools.go&#xA;    go generate -v -x -tags tools ./internal/tools/...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;go-run&#34;&gt;go run&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An alternative to this approach is to use &lt;code&gt;go run&lt;/code&gt; directly, which downloads tools to a cache but doesn&amp;rsquo;t install them and yet still gives you explicit versioning consistency across developer&amp;rsquo;s machines&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;//go:generate go run golang.org/x/tools/cmd/stringer@v0.25.0 -type=Scope -linecomment&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I then invoke go generation with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-Makefile&#34;&gt;.PHONY: go-gen&#xA;go-gen: ## Invoke go generate&#xA;    @# The `-x` flag prints the shell commands that `go generate` runs.&#xA;    go generate -v -x ./mustang/status/...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;If you&amp;rsquo;re developing whilst offline, then one advantage the tools.go pattern&#xA;has is that it works whilst offline because the tool is explicitly installed.&#xA;But to work around that with &lt;code&gt;go run&lt;/code&gt; you can set &lt;code&gt;export GOPROXY=direct&lt;/code&gt; and&#xA;as long as you have the module in your local cache you&amp;rsquo;ll be able to use it.&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-tools/</guid>
      <link>https://www.integralist.co.uk/posts/go-tools/</link>
      <pubDate>Mon, 12 May 2025 00:00:00 +0000</pubDate>
      <title>Managing project tools with Go</title>
    </item>
    <item>
      <description>&lt;p&gt;If you work on muliple &lt;a href=&#34;https://go.dev/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; projects, you&amp;rsquo;ll often find they require&#xA;different Go versions. So how do you handle switching between Go versions?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can&amp;rsquo;t rely on your package manager as it might only provide the latest&#xA;version of Go (such as is the case when using &lt;a href=&#34;https://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt; on macOS) or it might&#xA;not provide all prior Go versions (maybe only a subset). Then you have to decide&#xA;whether the &lt;em&gt;switch&lt;/em&gt; is something you do manually or automatically when you &lt;code&gt;cd&lt;/code&gt;&#xA;into a Go project directory (but how do you determine and implement that?).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically you&amp;rsquo;ll use a third-party tool that does this for you. I&amp;rsquo;ve&#xA;historically used a lot of tools. The last tool I used was&#xA;&lt;a href=&#34;https://github.com/stefanmaric/g&#34; target=&#34;_blank&#34;&gt;stefanmaric/g&lt;/a&gt; and it was working fine &amp;hellip;for a while, until one day&#xA;it stopped working and for the life of me I couldn&amp;rsquo;t figure out why.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with using a third-party tool is that &lt;em&gt;if&lt;/em&gt; it does go wrong, it&amp;rsquo;s&#xA;very hard to debug and fix. With this in mind, I decided I would have a go at&#xA;solving the problem in a way that worked for me.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-warning&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;⚠️ WARNING&lt;/p&gt;&lt;p&gt;This is NOT a perfect solution, and in some cases it&amp;rsquo;s a &lt;em&gt;poor&lt;/em&gt; solution.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In this article I&amp;rsquo;m going to show you the code I wrote to implement Go-version&#xA;switching, as well as covering some of the caveats of the approach I took. But&#xA;ultimately, this is a solution I&amp;rsquo;ve implemented from scratch and so I&#xA;intrinsically understand it and will understand how it works better than anyone&#xA;and will understand more easily what to do &lt;em&gt;if&lt;/em&gt; for some reason there&amp;rsquo;s a bug or&#xA;scenario that I didn&amp;rsquo;t account for when first creating it. This is why I provide&#xA;the above warning note. &lt;strong&gt;Feel free to use my approach, or use the code as an&#xA;example from which to build your &lt;em&gt;own&lt;/em&gt; solution.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;As an alternative, some people prefer to have a single Go version install&#xA;(i.e. GOROOT) and then when they use the &lt;code&gt;go&lt;/code&gt; binary to install other versions&#xA;they will simply create an alias (manually) or have a Makefile accept a&#xA;&lt;code&gt;GO_BIN&lt;/code&gt; override. It&amp;rsquo;s definitely a much simpler approach if you prefer that.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s dig in and see what we have&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;shell-structure&#34;&gt;Shell Structure&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, let&amp;rsquo;s start with how I like to structure my shell files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have a &lt;code&gt;.zshrc&lt;/code&gt; from which I then load in other shell scripts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid muddying the water I&amp;rsquo;ll show a truncated version:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you want the full version of the code we&amp;rsquo;re discussing,&lt;br&gt;&#xA;then refer to my &lt;a href=&#34;https://github.com/integralist/dotfiles&#34; target=&#34;_blank&#34;&gt;dotfiles repo&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;#!/usr/bin/zsh&#xA;&#xA;function load_script {&#xA;    local path=$1&#xA;    if test -f $path; then&#xA;        source $path&#xA;    else&#xA;        echo &amp;quot;no $path found&amp;quot;&#xA;    fi&#xA;}&#xA;&#xA;load_script ~/.config/zsh/tools.zsh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Cool, so we know we need a &lt;code&gt;tools.zsh&lt;/code&gt; script. Let&amp;rsquo;s take a look at the relevant&#xA;sections of that file. We&amp;rsquo;ll start with the exports&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;exports&#34;&gt;Exports&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;export GOPATH=&amp;quot;$HOME/go&amp;quot;&#xA;export GOROOT=&amp;quot;$HOME/.go&amp;quot;&#xA;export PATH=&amp;quot;$GOPATH/bin:$GOROOT/bin:$PATH&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;GOPATH&lt;/code&gt; is where we install Go CLI programs, and for our purposes it&amp;rsquo;s&#xA;where we will install our different Go versions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;GOROOT&lt;/code&gt; is where we&#xA;install our primary Go version (this is the Go version we start with and is the&#xA;version we keep up-to-date with the latest Go release).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;PATH&lt;/code&gt; is where our shell attempts to lookup executable binaries, such as&#xA;the &lt;code&gt;go&lt;/code&gt; binary.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can see we make sure &lt;code&gt;$GOPATH/bin&lt;/code&gt; is checked first, then failing that it&amp;rsquo;ll&#xA;check &lt;code&gt;$GOROOT/bin&lt;/code&gt;, before considering any other entries in the &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can probably already guess the approach I&amp;rsquo;m taking, but if not, it&amp;rsquo;s this:&#xA;by having &lt;code&gt;$GOPATH/bin&lt;/code&gt; as the first entry in my &lt;code&gt;$PATH&lt;/code&gt;, it means I can install&#xA;my different Go version binaries there, and then create a symlink for &lt;code&gt;go&lt;/code&gt; in&#xA;that same directory to point to the specific Go version binary I want to be&#xA;using.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;installing-go-for-goroot&#34;&gt;Installing Go for GOROOT&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The first thing we need to do is identify if we have Go installed at all. We do&#xA;this by checking if there is a &lt;code&gt;go&lt;/code&gt; binary file in our &lt;code&gt;$GOROOT/bin&lt;/code&gt; directory.&#xA;If there isn&amp;rsquo;t a file there, then we identify the latest Go version release and&#xA;download it into &lt;code&gt;$GOROOT/bin&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;if [ ! -f $GOROOT/bin/go ]; then&#xA;    mkdir -p &amp;quot;$GOPATH&amp;quot;&#xA;    mkdir -p &amp;quot;$GOROOT&amp;quot;&#xA;&#xA;    GO_VERSION=$(golatest)&#xA;    OS=$(uname | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)&#xA;    ARCH=$(uname -m)&#xA;    URL=&amp;quot;https://go.dev/dl/go${GO_VERSION}.${OS}-${ARCH}.tar.gz&amp;quot;&#xA;    TMP_DL=&amp;quot;/tmp/go.tar.gz&amp;quot;&#xA;&#xA;    echo &amp;quot;Downloading latest Go archive from $URL&amp;quot;&#xA;    curl -Lo &amp;quot;$TMP_DL&amp;quot; &amp;quot;$URL&amp;quot;&#xA;&#xA;    # Extract the tar.gz file to the installation directory&#xA;    # The --strip-components=1 skips the go/ directory within the archive.&#xA;    # This ensures the ~/.go directory contains bin/ rather than ~/.go/go/bin&#xA;    echo &amp;quot;Extracting Go archive to $GOROOT&amp;quot;&#xA;    tar -C &amp;quot;$GOROOT&amp;quot; --strip-components=1 -xzf &amp;quot;$TMP_DL&amp;quot;&#xA;&#xA;    # Cleanup the downloaded archive&#xA;    echo &amp;quot;Cleaning up Go archive from $TMP_DL&amp;quot;&#xA;    rm &amp;quot;$TMP_DL&amp;quot;&#xA;fi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve used &lt;code&gt;golatest&lt;/code&gt; in the above code. The implementation for that is as&#xA;follows:&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;alias golatest=&amp;quot;curl -L https://github.com/golang/go/tags 2&amp;gt;&amp;amp;1 | \&#xA;    rg &#39;/golang/go/releases/tag/go[\w.]+&#39; -o | \&#xA;    cut -d &#39;/&#39; -f 6 | \&#xA;    grep -v &#39;rc&#39; | \&#xA;    awk NR==1 | \&#xA;    rg &#39;\d.+&#39; -o&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;triggering-a-switch-on-directory-change&#34;&gt;Triggering a switch on directory change&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So the key part to all this is checking the current directory to see if we need&#xA;to download a different Go version. In the Zsh shell you have access to a&#xA;builtin function called &lt;code&gt;chpwd&lt;/code&gt; which runs every time you change directory.&#xA;Changing directory is typically done using &lt;code&gt;cd&lt;/code&gt; but it also works if you use a&#xA;tool like &lt;a href=&#34;https://github.com/ajeetdsouza/zoxide&#34; target=&#34;_blank&#34;&gt;ajeetdsouza/zoxide&lt;/a&gt; (like I do) to quickly jump around&#xA;common project directories.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;See the Zsh &lt;a href=&#34;https://zsh.sourceforge.io/Doc/Release/Functions.html#Hook-Functions&#34; target=&#34;_blank&#34;&gt;hook functions&lt;/a&gt; docs.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is the relevant parts of our &lt;code&gt;chpwd&lt;/code&gt; function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;function chpwd() {&#xA;    ls&#xA;&#xA;    # figure out go version&#xA;    #&#xA;    local v=&amp;quot;&amp;quot;&#xA;    if [ -e go.mod ]; then&#xA;        v=$(awk &#39;/^go [0-9]+\.[0-9]+/ { print $2 }&#39; go.mod)&#xA;        # go.mod isn&#39;t always going to contain a complete version (e.g. 1.20 vs 1.20.1)&#xA;        # we need a complete version for installing and symlinking.&#xA;        #&#xA;        if [[ ! &amp;quot;$v&amp;quot; =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then&#xA;            latest_patch=$(gh api repos/golang/go/tags --jq &#39;.[].name&#39; --paginate \&#xA;                | grep -E &amp;quot;^go${v}\.[0-9]+$&amp;quot; \&#xA;                | sed &#39;s/^go//&#39; \&#xA;                | sort -V \&#xA;                | tail -n 1)&#xA;            if [ -n &amp;quot;$latest_patch&amp;quot; ]; then&#xA;                v=&amp;quot;$latest_patch&amp;quot;&#xA;            else&#xA;                echo &amp;quot;Failed to fetch the latest patch version for $v&amp;quot;&#xA;                go_symlink_remove # remove symlink so the PATH lookup finds the GOROOT binary.&#xA;                v=&amp;quot;&amp;quot; # Ensure v is empty to prevent executing the install steps&#xA;            fi&#xA;        fi&#xA;    elif [ -e .go-version ]; then&#xA;        v=&amp;quot;$(cat .go-version)&amp;quot;&#xA;    fi&#xA;    if [ -n &amp;quot;$v&amp;quot; ]; then&#xA;        # create go dependencies cache directory if it doesn&#39;t exist.&#xA;        local cache_dir=&amp;quot;$HOME/.cache/go-deps&amp;quot;&#xA;        if [[ ! -d &amp;quot;$cache_dir&amp;quot; ]]; then&#xA;            mkdir -p &amp;quot;$HOME/.cache/go-deps&amp;quot;&#xA;        fi&#xA;        local cache_file=&amp;quot;$cache_dir/go$v&amp;quot;&#xA;&#xA;        if [[ ! -f &amp;quot;$cache_file&amp;quot; ]]; then&#xA;            go_install &amp;quot;$v&amp;quot; # installs the specified Go version&#xA;            go_symlink &amp;quot;$v&amp;quot; # ensures `go` now references the specified Go version&#xA;            go_tools # ensures we have all the tools we need for this Go version&#xA;            touch &amp;quot;$cache_file&amp;quot; # update last_modified date&#xA;        else&#xA;            go_symlink &amp;quot;$v&amp;quot; # ensures `go` now references the specified Go version&#xA;&#xA;            local current_day=$(date +%Y-%m-%d)&#xA;            local last_modified_day=$(date -r &amp;quot;$cache_file&amp;quot; +%Y-%m-%d)&#xA;&#xA;            # if the cache file was last modified on a different day, run the command&#xA;            if [ &amp;quot;$current_day&amp;quot; != &amp;quot;$last_modified_day&amp;quot; ]; then&#xA;                echo &amp;quot;updating go$v dependencies (last updated: $last_modified_day)&amp;quot;&#xA;                go_tools # ensures we have all the tools we need for this Go version&#xA;                touch &amp;quot;$cache_file&amp;quot; # update last_modified date&#xA;            fi&#xA;        fi&#xA;&#xA;        r # reload shell so starship can display the updated go version&#xA;    fi&#xA;&#xA;    # clean out any .DS_Store files&#xA;    #&#xA;    if [[ $PWD != $HOME ]]; then&#xA;        # find . -type f -name &#39;.DS_Store&#39; -delete&#xA;        fd &#39;.DS_Store&#39; --type f --hidden --absolute-path | xargs -I {} rm {}&#xA;    fi&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above script we do the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Check if the directory contains a &lt;code&gt;go.mod&lt;/code&gt; or a &lt;code&gt;.go-version&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If there&amp;rsquo;s a &lt;code&gt;go.mod&lt;/code&gt; then we check if it&amp;rsquo;s a &amp;lsquo;complete&amp;rsquo; version.&lt;/li&gt;&#xA;&lt;li&gt;If it&amp;rsquo;s not a complete version, we identify the latest patch available.&lt;/li&gt;&#xA;&lt;li&gt;If it&amp;rsquo;s a &lt;code&gt;.go-version&lt;/code&gt; then we know that will contain a full version.&lt;/li&gt;&#xA;&lt;li&gt;We store whatever version we find or calculate into &lt;code&gt;v&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;We then call some custom functions and pass them &lt;code&gt;v&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For that last bullet, the functions we call are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;go_install&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;go_symlink&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;go_tools&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The implementation for those functions are:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;# go_install installs the specified version&#xA;function go_install() {&#xA;  if [ -z &amp;quot;$1&amp;quot; ]; then&#xA;        echo &amp;quot;Pass a Go version (e.g. 1.21.13)&amp;quot;&#xA;    return&#xA;  fi&#xA;    local v=&amp;quot;$1&amp;quot;&#xA;    go install &amp;quot;golang.org/dl/go$v@latest&amp;quot;&#xA;    &amp;quot;$GOPATH/bin/go$v&amp;quot; download&#xA;    &amp;quot;$GOPATH/bin/go$v&amp;quot; version&#xA;}&#xA;&#xA;# go_symlink is called by chpwd to allow a different go version binary to be used.&#xA;# if the specified version binary doesn&#39;t exist, we install it first.&#xA;function go_symlink() {&#xA;  if [ -z &amp;quot;$1&amp;quot; ]; then&#xA;        echo &amp;quot;Pass a Go version (e.g. 1.21.13)&amp;quot;&#xA;    return&#xA;  fi&#xA;    local v=$1&#xA;    if [ ! -f &amp;quot;$GOPATH/bin/go$v&amp;quot; ]; then&#xA;        go_install &amp;quot;$v&amp;quot;&#xA;    fi&#xA;    ln -sf &amp;quot;$GOPATH/bin/go$v&amp;quot; &amp;quot;$GOPATH/bin/go&amp;quot;&#xA;}&#xA;&#xA;# go_tools installs/updates necessary Go tools.&#xA;function go_tools {&#xA;  local golangcilatest=$(curl -s &amp;quot;https://github.com/golangci/golangci-lint/releases&amp;quot; | \&#xA;    grep -o &#39;tag/v[0-9]\+\.[0-9]\+\.[0-9]\+&#39; | head -n 1 | cut -d &#39;/&#39; -f 2)&#xA;  curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \&#xA;    sh -s -- -b $(go env GOPATH)/bin &amp;quot;$golangcilatest&amp;quot;&#xA;  go install github.com/rakyll/gotest@latest&#xA;  go install github.com/mgechev/revive@latest&#xA;  go install golang.org/x/tools/gopls@latest&#xA;  go install mvdan.cc/gofumpt@latest&#xA;  go install honnef.co/go/tools/cmd/staticcheck@latest # https://github.com/dominikh/go-tools&#xA;  go install golang.org/x/vuln/cmd/govulncheck@latest&#xA;  go install github.com/go-delve/delve/cmd/dlv@latest&#xA;  go install go.uber.org/nilaway/cmd/nilaway@latest&#xA;  go install golang.org/x/tools/cmd/goimports@latest&#xA;  go install github.com/incu6us/goimports-reviser/v3@latest&#xA;  go install github.com/google/gops@latest&#xA;  go install github.com/securego/gosec/v2/cmd/gosec@latest&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, we run &lt;code&gt;r&lt;/code&gt; which is an alias that reloads the &lt;code&gt;.zshrc&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;alias r=&amp;quot;source ~/.zshrc&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Why do we reload the shell configuration? Well, I use the &lt;a href=&#34;https://starship.rs/&#34; target=&#34;_blank&#34;&gt;Starship&lt;/a&gt; shell&#xA;prompt, and that has its own logic for determining the Go version, and now with&#xA;the above workflow it often reports the wrong Go version. But once I reload my&#xA;shell configuration it&amp;rsquo;ll pick up the &lt;code&gt;go&lt;/code&gt; binary that is now being symlinked to&#xA;a specific Go version.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, there&amp;rsquo;s a performance improvement I made to the code (which you can see in&#xA;the earlier code snippet but I didn&amp;rsquo;t explain):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;# create go dependencies cache directory if it doesn&#39;t exist.&#xA;local cache_dir=&amp;quot;$HOME/.cache/go-deps&amp;quot;&#xA;if [[ ! -d &amp;quot;$cache_dir&amp;quot; ]]; then&#xA;    mkdir -p &amp;quot;$HOME/.cache/go-deps&amp;quot;&#xA;fi&#xA;local cache_file=&amp;quot;$cache_dir/go$v&amp;quot;&#xA;&#xA;if [[ ! -f &amp;quot;$cache_file&amp;quot; ]]; then&#xA;    go_install &amp;quot;$v&amp;quot; # installs the specified Go version&#xA;    go_symlink &amp;quot;$v&amp;quot; # ensures `go` now references the specified Go version&#xA;    go_tools # ensures we have all the tools we need for this Go version&#xA;    touch &amp;quot;$cache_file&amp;quot; # update last_modified date&#xA;else&#xA;    go_symlink &amp;quot;$v&amp;quot; # ensures `go` now references the specified Go version&#xA;&#xA;    local current_day=$(date +%Y-%m-%d)&#xA;    local last_modified_day=$(date -r &amp;quot;$cache_file&amp;quot; +%Y-%m-%d)&#xA;&#xA;    # if the cache file was last modified on a different day, run the command&#xA;    if [ &amp;quot;$current_day&amp;quot; != &amp;quot;$last_modified_day&amp;quot; ]; then&#xA;        echo &amp;quot;updating go$v dependencies (last updated: $last_modified_day)&amp;quot;&#xA;        go_tools # ensures we have all the tools we need for this Go version&#xA;        touch &amp;quot;$cache_file&amp;quot; # update last_modified date&#xA;    fi&#xA;fi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That improvement was to check if a cache file exists for the Go version, and if&#xA;so, we&amp;rsquo;ll see if the file was updated at some point in the last day. If it has&#xA;been updated already then we don&amp;rsquo;t bother updating the Go tools and dependencies&#xA;for the specified Go version&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We only really want to do that &lt;em&gt;once&lt;/em&gt; a day, otherwise every time you change&#xA;directory to another Go project it will unnecessarily downloads dependencies you&#xA;already have and that takes time.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-install-and-switch/</guid>
      <link>https://www.integralist.co.uk/posts/go-install-and-switch/</link>
      <pubDate>Sun, 02 Feb 2025 00:00:00 +0000</pubDate>
      <title>Manually install and auto-switch Golang versions</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;goroutines&#34;&gt;Goroutines&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;go&lt;/code&gt; keyword is used to start a goroutine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A goroutine is a lightweight, managed thread used by the Go runtime to run&#xA;functions concurrently.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unlike OS threads, which have a fixed stack size (often around 1MB), goroutines&#xA;start with a very small stack, around 2KB, and can grow or shrink dynamically as&#xA;needed. This makes it possible to run thousands or even millions of goroutines&#xA;simultaneously, depending on the available memory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Goroutines are sometimes compared to &amp;ldquo;green threads,&amp;rdquo; which are threads that are&#xA;scheduled in user space rather than by the OS. The problem with green threads is&#xA;that they may not leverage multiple CPU cores efficiently since they don&amp;rsquo;t&#xA;interact directly with the OS’s scheduler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Goroutines are similar to green threads in that they are scheduled by the Go&#xA;runtime rather than the OS. However, they differ in a crucial way: Go uses a&#xA;model called Mscheduling, where the Go runtime maps multiple goroutines (M) onto&#xA;multiple OS threads (N). This allows the runtime to distribute goroutines across&#xA;multiple CPU cores when possible, making Go’s concurrency model more efficient&#xA;and scalable than traditional green threads.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;The following example uses a &lt;code&gt;time.Sleep&lt;/code&gt; to wait for the goroutine to finish.&lt;br&gt;&#xA;This is done for simplicity. Do NOT use this approach.&lt;br&gt;&#xA;I&amp;rsquo;ll explain alternative options afterwards.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func sayHello() {&#xA;    fmt.Println(&amp;quot;Hello from a goroutine!&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;    go sayHello() // Launches sayHello in a new goroutine&#xA;&#xA;    fmt.Println(&amp;quot;Hello from main!&amp;quot;)&#xA;    time.Sleep(1 * time.Second) // Wait for the goroutine to complete (only for example)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/SdOdZ90-exI&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/SdOdZ90-exI&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;In Go, the &lt;code&gt;main&lt;/code&gt; function is effectively the &amp;ldquo;initial&amp;rdquo; goroutine.&lt;br&gt;&#xA;When a Go program starts, the Go runtime creates a goroutine to run &lt;code&gt;main&lt;/code&gt;.&lt;br&gt;&#xA;This main goroutine can then spawn additional goroutines as needed.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;channels&#34;&gt;Channels&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Channels in Go are a powerful way to communicate between goroutines and to&#xA;synchronize them. They allow you to send and receive values across goroutines,&#xA;and they help avoid race conditions by enabling safe data sharing.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;Sending and receiving channel messages can&#xA;&lt;a href=&#34;https://go.dev/tour/concurrency/2&#34; target=&#34;_blank&#34;&gt;block&lt;/a&gt;.&lt;br&gt;&#xA;In the following example the &lt;code&gt;&amp;lt;-ch&lt;/code&gt; BLOCKS the &lt;code&gt;main()&lt;/code&gt; function.&lt;br&gt;&#xA;While the &lt;code&gt;ch &amp;lt;-&lt;/code&gt; BLOCKS the &lt;code&gt;sendMessage()&lt;/code&gt; function.&lt;br&gt;&#xA;This can cause a deadlock, hence we use a goroutine to unblock things.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;)&#xA;&#xA;func sendMessage(ch chan string) {&#xA;    ch &amp;lt;- &amp;quot;Hello from a goroutine!&amp;quot; // Send a message to the channel&#xA;                                    // ⚠️ This BLOCKS but as it&#39;s running in a goroutine &#xA;                                    // the program is unaffected.&#xA;}&#xA;&#xA;func main() {&#xA;    // Create a new channel of type string&#xA;    ch := make(chan string)&#xA;&#xA;    // Start a goroutine to send a message&#xA;    go sendMessage(ch)&#xA;&#xA;    // Receive the message from the channel&#xA;    msg := &amp;lt;-ch // ⚠️ This BLOCKS the program (hence sendMessage() runs in a goroutine)&#xA;    fmt.Println(msg) // Output: Hello from a goroutine!&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/2Qn_NacVw-0&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/2Qn_NacVw-0&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;You can &lt;code&gt;range&lt;/code&gt; over a channel, but the loop will never stop unless the&#xA;channel is closed.&lt;br&gt;&#xA;So when ranging over a channel, think how the program can proceed and when is&#xA;the channel going to be closed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;[!NOTE]&#xA;Depending on what you application needs, you can create&#xA;&lt;a href=&#34;https://go.dev/tour/concurrency/3&#34; target=&#34;_blank&#34;&gt;buffered&lt;/a&gt; channels.&lt;br&gt;&#xA;Sends to a buffered channel block only when the buffer is full.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;[!TIP]&#xA;The most crucial best practice is to close the channel from the sender side, not the receiver.&lt;br&gt;&#xA;The sender is the goroutine that writes data to the channel.&lt;br&gt;&#xA;Hence the sender knows when there&amp;rsquo;s no more data to be sent, not the receiver.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;select-statement&#34;&gt;Select Statement&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;select&lt;/code&gt; statement is used to wait on multiple channel operations.&lt;br&gt;&#xA;It blocks until one of its cases can proceed, which makes it essential for&#xA;handling multiple asynchronous tasks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use &lt;code&gt;select&lt;/code&gt; when you have multiple channels to listen to, and you want to&#xA;respond to whichever channel receives data first.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;In the following example, the first goroutine uses a &lt;code&gt;time.Sleep&lt;/code&gt;.&lt;br&gt;&#xA;This is to simulate the operation taking a long time.&lt;br&gt;&#xA;It results in the &lt;code&gt;select&lt;/code&gt; pulling a value from the second goroutine.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    ch1 := make(chan string)&#xA;    ch2 := make(chan string)&#xA;&#xA;    go func() {&#xA;        time.Sleep(1 * time.Second)&#xA;        ch1 &amp;lt;- &amp;quot;result from ch1&amp;quot;&#xA;    }()&#xA;&#xA;    go func() {&#xA;        ch2 &amp;lt;- &amp;quot;result from ch2&amp;quot;&#xA;    }()&#xA;&#xA;    select {&#xA;    case msg1 := &amp;lt;-ch1:&#xA;        fmt.Println(&amp;quot;Received:&amp;quot;, msg1)&#xA;    case msg2 := &amp;lt;-ch2:&#xA;        fmt.Println(&amp;quot;Received:&amp;quot;, msg2)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/HXe-bZ__EEy&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/HXe-bZ__EEy&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A common use case for &lt;code&gt;select&lt;/code&gt; is to timeout a potential deadlock:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;In the following example we use &lt;code&gt;time.After&lt;/code&gt; to cause a timeout.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    // Create an unbuffered channel&#xA;    ch := make(chan string)&#xA;&#xA;    // Start a goroutine that simulates a delayed send&#xA;    go func() {&#xA;        time.Sleep(3 * time.Second)   // Simulate a delay&#xA;        ch &amp;lt;- &amp;quot;Hello from goroutine!&amp;quot; // Send a message after delay&#xA;    }()&#xA;&#xA;    select {&#xA;    case msg := &amp;lt;-ch:&#xA;        fmt.Println(&amp;quot;Received:&amp;quot;, msg)&#xA;    case &amp;lt;-time.After(2 * time.Second): // Timeout after 2 seconds&#xA;        fmt.Println(&amp;quot;Timeout! No message received.&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/6BMPeUKdqkg&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/6BMPeUKdqkg&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;wait-groups&#34;&gt;Wait Groups&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &lt;code&gt;sync.WaitGroup&lt;/code&gt; waits for a collection of goroutines to finish. It helps&#xA;coordinate a group of goroutines and ensures the program waits until all of them&#xA;have completed before proceeding.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use a &lt;code&gt;WaitGroup&lt;/code&gt; when you need to wait for multiple goroutines to finish before&#xA;moving on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this example, a &lt;code&gt;sync.WaitGroup&lt;/code&gt; is used to wait for three goroutines to&#xA;complete. Each goroutine represents a worker, and each one calls &lt;code&gt;wg.Done()&lt;/code&gt; to&#xA;signal that it&amp;rsquo;s finished. The &lt;code&gt;main&lt;/code&gt; function calls &lt;code&gt;wg.Wait()&lt;/code&gt; to block until&#xA;all workers are done.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;func worker(id int, wg *sync.WaitGroup) {&#xA;    defer wg.Done() // Decrement counter when goroutine completes&#xA;    fmt.Printf(&amp;quot;Worker %d starting\n&amp;quot;, id)&#xA;    fmt.Printf(&amp;quot;Worker %d done\n&amp;quot;, id)&#xA;}&#xA;&#xA;func main() {&#xA;    var wg sync.WaitGroup&#xA;&#xA;    for i := range 3 {&#xA;        wg.Add(1) // Track each goroutine started&#xA;        go worker(i, &amp;amp;wg)&#xA;    }&#xA;&#xA;    // Wait for all goroutines to finish&#xA;    wg.Wait()&#xA;&#xA;    fmt.Println(&amp;quot;All workers done.&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/LhEdSQIPp1R&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/LhEdSQIPp1R&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;💡 &lt;strong&gt;UPDATE:&lt;/strong&gt;&lt;br&gt;&#xA;As of Go 1.25 you no longer need to &lt;code&gt;wg.Add&lt;/code&gt;/&lt;code&gt;wg.Defer&lt;/code&gt; for simple cases.&lt;br&gt;&#xA;Instead you can just use &lt;code&gt;wg.Go()&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    var wg sync.WaitGroup&#xA;&#xA;    wg.Go(func() {&#xA;        fmt.Println(&amp;quot;go is awesome&amp;quot;)&#xA;    })&#xA;&#xA;    wg.Go(func() {&#xA;        fmt.Println(&amp;quot;cats are cute&amp;quot;)&#xA;    })&#xA;&#xA;    wg.Wait()&#xA;    fmt.Println(&amp;quot;done&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://go.dev/play/p/b_WdOO7IYVM?v=gotip&#34; target=&#34;_blank&#34;&gt;https://go.dev/play/p/b_WdOO7IYVM?v=gotip&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;error-groups&#34;&gt;Error Groups&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://pkg.go.dev/golang.org/x/sync/errgroup&#34; target=&#34;_blank&#34;&gt;errgroup&lt;/a&gt; package is like a&#xA;&lt;code&gt;sync.WaitGroup&lt;/code&gt; but with added capabilities for error handling and context&#xA;cancellation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;While a WaitGroup simply waits for a collection of goroutines to finish, an&#xA;errgroup also collects any errors returned by those goroutines and can cancel&#xA;all of them if one fails.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example, when one worker fails, it triggers a cancellation in&#xA;the other workers (some might complete in time, but those that don&amp;rsquo;t will be&#xA;forcefully cancelled):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;context&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;&#xA;    &amp;quot;golang.org/x/sync/errgroup&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    ctx := context.Background()&#xA;&#xA;    // errgroup.WithContext creates a new Group and a derived Context.&#xA;    // The errgroup context is cancelled when the first goroutine returns a non-nil&#xA;    // error or when the g.Wait function returns.&#xA;    g, ctx := errgroup.WithContext(ctx)&#xA;&#xA;    // List of URLs to fetch&#xA;    urls := []string{&#xA;        &amp;quot;https://http-me.fastly.dev/status=200&amp;quot;,&#xA;        &amp;quot;https://http-me.fastly.dev/?wait=1000&amp;amp;status=201&amp;quot;, // This never completes (i.e. goroutine is cancelled)&#xA;        &amp;quot;https://http-me.fastly.dev/?wait=1000&amp;amp;status=202&amp;quot;, // This never completes (i.e. goroutine is cancelled)&#xA;        &amp;quot;https://http-me.fastly.dev/status=500&amp;quot;,            // This one will return an error&#xA;    }&#xA;&#xA;    for _, url := range urls {&#xA;        u := url&#xA;&#xA;        // Start a goroutine for each URL&#xA;        g.Go(func() error {&#xA;            fmt.Println(&amp;quot;Goroutine for &amp;quot;, u)&#xA;&#xA;            // Create a request with context&#xA;            req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)&#xA;            if err != nil {&#xA;                return fmt.Errorf(&amp;quot;creating request: %w&amp;quot;, err)&#xA;            }&#xA;&#xA;            resp, err := http.DefaultClient.Do(req)&#xA;            if err != nil {&#xA;                return fmt.Errorf(&amp;quot;request failed: %w&amp;quot;, err)&#xA;            }&#xA;            defer resp.Body.Close()&#xA;&#xA;            // Treat non-200 status codes (1xx, 3xx, 4xx, 5xx) as errors&#xA;            if resp.StatusCode &amp;lt; http.StatusOK || resp.StatusCode &amp;gt;= http.StatusMultipleChoices {&#xA;                return fmt.Errorf(&amp;quot;non-200 status: %d from %s&amp;quot;, resp.StatusCode, u)&#xA;            }&#xA;&#xA;            select {&#xA;            case &amp;lt;-time.After(time.Millisecond):&#xA;                // don&#39;t block forever, just enough to check context.Done&#xA;            case &amp;lt;-ctx.Done():&#xA;                // This block is executed if the context is cancelled before the work is finished.&#xA;                fmt.Printf(&amp;quot;Goroutine %s cancelled\n&amp;quot;, u)&#xA;                return ctx.Err()&#xA;            }&#xA;&#xA;            fmt.Printf(&amp;quot;Successfully fetched: %s\n&amp;quot;, u)&#xA;            return nil&#xA;        })&#xA;    }&#xA;&#xA;    // Wait for all goroutines to complete or any to return an error&#xA;    if err := g.Wait(); err != nil {&#xA;        fmt.Printf(&amp;quot;Error: %v\n&amp;quot;, err)&#xA;    } else {&#xA;        fmt.Println(&amp;quot;All fetches succeeded.&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the program is non-deterministic. So, for example, you might see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Goroutine for  https://http-me.fastly.dev/status=500&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=202&#xA;Goroutine for  https://http-me.fastly.dev/status=200&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=201&#xA;Error: non-200 status: 500 from https://http-me.fastly.dev/status=500&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the above output no goroutine is successful. The error is picked up&#xA;from the &lt;code&gt;status=500&lt;/code&gt; URL and so all other goroutines are cancelled immediately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where as if you run the code again you might see this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Goroutine for  https://http-me.fastly.dev/status=500&#xA;Goroutine for  https://http-me.fastly.dev/status=200&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=201&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=202&#xA;Goroutine https://http-me.fastly.dev/status=200 cancelled&#xA;Error: non-200 status: 500 from https://http-me.fastly.dev/status=500&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the above output we now see one of the goroutines were explicitly&#xA;cancelled, i.e. the &lt;code&gt;select&lt;/code&gt; statement had time to run the check on the&#xA;&lt;code&gt;ctx.Done()&lt;/code&gt; call.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we want to see any of these goroutines fail we need to play around with the&#xA;delays to give one of them a chance of succeeding. So something like this would&#xA;do it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;urls := []string{&#xA;    &amp;quot;https://http-me.fastly.dev/status=200&amp;quot;,&#xA;    &amp;quot;https://http-me.fastly.dev/?wait=1000&amp;amp;status=201&amp;quot;,&#xA;    &amp;quot;https://http-me.fastly.dev/?wait=1000&amp;amp;status=202&amp;quot;,&#xA;    &amp;quot;https://http-me.fastly.dev/?wait=500&amp;amp;status=500&amp;quot;,&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice we&amp;rsquo;ve set a smaller delay (&lt;code&gt;wait=500&lt;/code&gt;) on the &lt;code&gt;status=500&lt;/code&gt; URL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When running the code again we&amp;rsquo;d see something like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Goroutine for  https://http-me.fastly.dev/?wait=500&amp;amp;status=500&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=201&#xA;Goroutine for  https://http-me.fastly.dev/status=200&#xA;Goroutine for  https://http-me.fastly.dev/?wait=1000&amp;amp;status=202&#xA;Successfully fetched: https://http-me.fastly.dev/status=200&#xA;Error: non-200 status: 500 from https://http-me.fastly.dev/?wait=500&amp;amp;status=500&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the above output we now see at least one successful case.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;You can limit the number of active goroutines in the group with:&lt;br&gt;&#xA;&lt;code&gt;g.SetLimit(10)&lt;/code&gt;&lt;br&gt;&#xA;Calls to &lt;code&gt;g.Go&lt;/code&gt; will block until an active goroutine can be added.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;mutex&#34;&gt;Mutex&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go&amp;rsquo;s &lt;code&gt;sync.Mutex&lt;/code&gt; provides mutual exclusion, allowing only one goroutine at a&#xA;time to access a critical section of code.&lt;br&gt;&#xA;While &lt;code&gt;sync.RWMutex&lt;/code&gt; is a variant that allows multiple readers or a single&#xA;writer but not both.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use &lt;code&gt;sync.Mutex&lt;/code&gt; or &lt;code&gt;sync.RWMutex&lt;/code&gt; when you need fine-grained control over data&#xA;access and want to protect shared data from race conditions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the below example &lt;code&gt;sync.Mutex&lt;/code&gt; ensures that only one goroutine modifies&#xA;&lt;code&gt;counter.value&lt;/code&gt; at a time, preventing race conditions:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;type Counter struct {&#xA;    mu    sync.Mutex&#xA;    value int&#xA;}&#xA;&#xA;func (c *Counter) Increment() {&#xA;    c.mu.Lock()&#xA;    defer c.mu.Unlock()&#xA;    c.value++&#xA;}&#xA;&#xA;func (c *Counter) Value() int {&#xA;    c.mu.Lock()&#xA;    defer c.mu.Unlock()&#xA;    return c.value&#xA;}&#xA;&#xA;func main() {&#xA;    counter := &amp;amp;Counter{}&#xA;    var wg sync.WaitGroup&#xA;&#xA;    for range 10 {&#xA;        wg.Add(1)&#xA;        go func() {&#xA;            defer wg.Done()&#xA;            counter.Increment()&#xA;        }()&#xA;    }&#xA;&#xA;    wg.Wait()&#xA;    &#xA;    fmt.Println(&amp;quot;Final Counter:&amp;quot;, counter.Value())&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/VIbNkQaPfZI&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/VIbNkQaPfZI&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;The use of &lt;code&gt;defer&lt;/code&gt; in the &lt;code&gt;Increment()&lt;/code&gt; method is redundant.&lt;br&gt;&#xA;It&amp;rsquo;s more useful for long complex functions where errors can occur.&lt;br&gt;&#xA;Here I should have just placed the &lt;code&gt;Unlock()&lt;/code&gt; call after the &lt;code&gt;c.value++&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;atomic-operations&#34;&gt;Atomic Operations&lt;/h2&gt;&#xA;&#xA;&lt;!--alex ignore simple--&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;sync/atomic&lt;/code&gt; package provides low-level atomic operations on simple types&#xA;like integers and pointers, ensuring operations are performed atomically.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use atomic operations when you need lock-free synchronization for counters or&#xA;flags, but only for basic integer or pointer manipulations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example, &lt;code&gt;atomic.AddInt32&lt;/code&gt; safely increments &lt;code&gt;counter&lt;/code&gt; without&#xA;a lock, making it ideal for high-performance counters or flags:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;    &amp;quot;sync/atomic&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    var counter int32&#xA;    var wg sync.WaitGroup&#xA;&#xA;    for range 10 {&#xA;        wg.Add(1)&#xA;        go func() {&#xA;            defer wg.Done()&#xA;            atomic.AddInt32(&amp;amp;counter, 1)&#xA;        }()&#xA;    }&#xA;&#xA;    wg.Wait()&#xA;    &#xA;    fmt.Println(&amp;quot;Final Counter:&amp;quot;, atomic.LoadInt32(&amp;amp;counter))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/qsRPoC4GPNv&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/qsRPoC4GPNv&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;once&#34;&gt;Once&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go&amp;rsquo;s &lt;code&gt;sync.Once&lt;/code&gt; ensures that a function only executes once, even if multiple&#xA;goroutines attempt to run it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use &lt;code&gt;sync.Once&lt;/code&gt; when you need to perform a one-time initialization, such as&#xA;setting up a shared resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example, even though multiple goroutines call&#xA;&lt;code&gt;once.Do(initialize)&lt;/code&gt;, &lt;code&gt;initialize&lt;/code&gt; only runs once. This is especially useful&#xA;for lazy initialization of global resources:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;var once sync.Once&#xA;&#xA;func initialize() {&#xA;    fmt.Println(&amp;quot;Initializing...&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;    var wg sync.WaitGroup&#xA;    for range 3 {&#xA;        wg.Add(1)&#xA;        go func() {&#xA;            defer wg.Done()&#xA;            once.Do(initialize)&#xA;        }()&#xA;    }&#xA;    wg.Wait()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/5J1ApCPc1iU&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/5J1ApCPc1iU&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go&amp;rsquo;s &lt;code&gt;context.Context&lt;/code&gt; is not a strict concurrency primitive but is widely used&#xA;to manage timeouts, cancellations, and deadlines across goroutines.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;You&amp;rsquo;ve seen context used in the &lt;a href=&#34;#error-groups&#34;&gt;Error Groups&lt;/a&gt; example earlier.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Use &lt;code&gt;context.Context&lt;/code&gt; to signal cancellation or control the lifespan of&#xA;goroutines, particularly in networked or long-running tasks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example, &lt;code&gt;context.WithTimeout&lt;/code&gt; creates a context that&#xA;automatically cancels after 1 second, which is useful for controlling tasks that&#xA;may hang or take too long:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;context&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func process(ctx context.Context) {&#xA;    select {&#xA;    case &amp;lt;-time.After(2 * time.Second): // use time.After to simulate slow operation&#xA;        fmt.Println(&amp;quot;Completed work&amp;quot;)&#xA;    case &amp;lt;-ctx.Done():&#xA;        fmt.Println(&amp;quot;Work cancelled&amp;quot;)&#xA;    }&#xA;}&#xA;&#xA;func main() {&#xA;    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)&#xA;    defer cancel()&#xA;&#xA;    go process(ctx)&#xA;&#xA;    time.Sleep(2 * time.Second)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/diSmAp0SJkg&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/diSmAp0SJkg&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;map&#34;&gt;Map&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;sync&lt;/code&gt; package has a &lt;a href=&#34;https://pkg.go.dev/sync#Map&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/a&gt; type which you&#xA;will likely not need to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Go authors even document it as such&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The Map type is specialized. Most code should use a plain Go map instead, with&#xA;separate locking or coordination, for better type safety and to make it easier&#xA;to maintain other invariants along with the map content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Map type is optimized for two common use cases: (1) when the entry for a&#xA;given key is only ever written once but read many times, as in caches that&#xA;only grow, or (2) when multiple goroutines read, write, and overwrite entries&#xA;for disjoint sets of keys. In these two cases, use of a Map may significantly&#xA;reduce lock contention compared to a Go map paired with a separate Mutex or&#xA;RWMutex.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;conditions&#34;&gt;Conditions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go&amp;rsquo;s &lt;code&gt;sync.Cond&lt;/code&gt; is probably the most confusing and hard to use of all&#xA;concurrency tools (hence I&amp;rsquo;ve left it till last). It&amp;rsquo;s used for signaling&#xA;between goroutines. It lets goroutines wait until they are notified to continue,&#xA;which is useful when one goroutine needs to wait for a certain condition to be&#xA;met by another goroutine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Use &lt;code&gt;sync.Cond&lt;/code&gt; when you need goroutines to wait for certain conditions, such as&#xA;producer-consumer scenarios.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example, &lt;code&gt;cond.Wait()&lt;/code&gt; blocks until &lt;code&gt;cond.Signal()&lt;/code&gt; is called.&#xA;It&amp;rsquo;s useful for waiting on complex conditions where other primitives like &lt;code&gt;chan&lt;/code&gt;&#xA;may not be ideal:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;The call to &lt;code&gt;cond.L.Lock()&lt;/code&gt; in the main goroutine just before &lt;code&gt;for !ready&lt;/code&gt; is&#xA;required, otherwise you&amp;rsquo;ll get the error &lt;code&gt;fatal error: sync: unlock of unlocked mutex&lt;/code&gt;. This is because &lt;code&gt;cond.Wait()&lt;/code&gt; expects the caller to hold the&#xA;lock before calling &lt;code&gt;Wait()&lt;/code&gt; (see &lt;a href=&#34;https://youtu.be/VAV2h1GdgE0?si=cqErfqLXnWOgmcsh&#34; target=&#34;_blank&#34;&gt;this&#xA;video&lt;/a&gt; for details). Once&#xA;&lt;code&gt;Wait()&lt;/code&gt; returns, it reacquires the lock, ensuring the main goroutine can&#xA;safely check ready and exit the loop.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    var mu sync.Mutex&#xA;    cond := sync.NewCond(&amp;amp;mu)&#xA;    ready := false&#xA;&#xA;    go func() {&#xA;        time.Sleep(1 * time.Second)&#xA;        cond.L.Lock()&#xA;        ready = true&#xA;        cond.L.Unlock()&#xA;        cond.Signal() // Notify one waiting goroutine&#xA;    }()&#xA;&#xA;    cond.L.Lock()&#xA;    for !ready {&#xA;        cond.Wait() // Wait until condition is met&#xA;    }&#xA;    fmt.Println(&amp;quot;Ready is true, proceeding.&amp;quot;)&#xA;    cond.L.Unlock()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/n_txZaH7lPA&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/n_txZaH7lPA&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example we have multiple worker goroutines waiting on a shared&#xA;condition to be &amp;ldquo;notified.&amp;rdquo; We&amp;rsquo;ll see how both &lt;code&gt;.Signal()&lt;/code&gt; and &lt;code&gt;.Broadcast()&lt;/code&gt;&#xA;work when notifying waiting goroutines:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func worker(id int, cond *sync.Cond) {&#xA;    cond.L.Lock() // Lock the condition&#xA;    defer cond.L.Unlock()&#xA;&#xA;    fmt.Printf(&amp;quot;Worker %d is waiting\n&amp;quot;, id)&#xA;    cond.Wait() // Wait for a signal or broadcast&#xA;    fmt.Printf(&amp;quot;Worker %d is proceeding\n&amp;quot;, id)&#xA;}&#xA;&#xA;func main() {&#xA;    lock := &amp;amp;sync.Mutex{}&#xA;    cond := sync.NewCond(lock)&#xA;&#xA;    // Start multiple worker goroutines that will wait on the condition&#xA;    for i := range 3 {&#xA;        go worker(i, cond)&#xA;    }&#xA;&#xA;    // Allow time for all workers to start and wait&#xA;    time.Sleep(1 * time.Second)&#xA;&#xA;    // Use Signal to wake up one goroutine&#xA;    fmt.Println(&amp;quot;Notifying one worker&amp;quot;)&#xA;    cond.Signal() // Notifies one waiting worker&#xA;    time.Sleep(1 * time.Second)&#xA;&#xA;    // Use Broadcast to wake up all remaining goroutines&#xA;    fmt.Println(&amp;quot;Broadcasting to all remaining workers&amp;quot;)&#xA;    cond.Broadcast() // Notifies all remaining waiting workers&#xA;&#xA;    // Allow time for all goroutines to complete&#xA;    time.Sleep(2 * time.Second)&#xA;    fmt.Println(&amp;quot;Main function exiting.&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://play.golang.com/p/41ibtmUmKaN&#34; target=&#34;_blank&#34;&gt;https://play.golang.com/p/41ibtmUmKaN&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each worker goroutine locks the condition, calls &lt;code&gt;cond.Wait()&lt;/code&gt;, and then waits.&#xA;This releases the lock (as we now understand from the earlier IMPORTANT note,&#xA;see above if you missed it), allowing other goroutines to call &lt;code&gt;Wait()&lt;/code&gt; as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;cond.Signal()&lt;/code&gt; call in the &lt;code&gt;main&lt;/code&gt; function wakes up one of the waiting&#xA;goroutines, allowing it to proceed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After a short delay, &lt;code&gt;cond.Broadcast()&lt;/code&gt; wakes up all remaining waiting&#xA;goroutines, allowing them to proceed simultaneously.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is useful for scenarios where multiple tasks need to wait for a common&#xA;event or state change to proceed.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Notifications are not ordered.&lt;br&gt;&#xA;Any one of the waiting goroutines can be chosen to proceed first.&lt;br&gt;&#xA;Broadcast ensures that all waiting goroutines eventually proceed.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now you might be thinking &amp;ldquo;hmm, it looks like I could use channels instead and&#xA;they&amp;rsquo;re more idiomatic&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, here are some reasons for why you might need to choose &lt;code&gt;sync.Cond&lt;/code&gt; over&#xA;channels:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;p&gt;Fine-Grained Control: &lt;code&gt;sync.Cond&lt;/code&gt; allows precise control over waiting and&#xA;signaling, suitable for cases where specific conditions must be checked or&#xA;managed.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Broadcast Capability: Broadcasting to multiple goroutines is straightforward&#xA;with &lt;code&gt;sync.Cond&lt;/code&gt;, whereas channels require individual signaling, which can be&#xA;inefficient.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Reduced Complexity for State-Based Waiting: &lt;code&gt;sync.Cond&lt;/code&gt; is ideal for&#xA;situations where goroutines need to wait for specific conditions to be true,&#xA;rather than for individual values or events passed through a channel.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Avoiding Channel Overhead: Channels introduce buffering and management&#xA;overhead, especially with many goroutines, whereas &lt;code&gt;sync.Cond&lt;/code&gt; relies on a&#xA;shared mutex with a direct wait/notify mechanism, which is often faster.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;In summary, &lt;code&gt;sync.Cond&lt;/code&gt; is best suited for use cases that involve waiting for&#xA;and signaling conditions, especially when you need more control over&#xA;synchronization and when goroutines are reacting to shared state changes rather&#xA;than discrete message passing.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;real-examples&#34;&gt;Real Examples&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here are some real world application code I&amp;rsquo;ve had to write.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;bulk-deletion-api&#34;&gt;Bulk Deletion API&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Below is a &amp;lsquo;real world&amp;rsquo; example where we need to delete a bunch of keys from a&#xA;data store.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The API that is provided, does not support bulk deleting of keys.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The API does provide an endpoint that lets us paginate the available keys, and&#xA;we then need to stream that information as quickly as possible using a pool of&#xA;goroutines coordinated with both channels and wait groups.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s a nice example because it brings together several different concurrency&#xA;primitives (goroutines, channels, select, wait groups, atomic operations).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-tip&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;💡 TIP&lt;/p&gt;&lt;p&gt;Keep reading after the code snippet for a brief breakdown of what the code&#xA;does.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;const (&#xA;    // PoolSize is the goroutine/thread-pool size.&#xA;    // Each pool will take a &#39;key&#39; from a channel and issue a DELETE request.&#xA;    const PoolSize int = 100&#xA;&#xA;    // MaxErrors is the maximum number of errors we&#39;ll allow before&#xA;    // stopping the goroutines from executing.&#xA;    const MaxErrors int = 100&#xA;)&#xA;&#xA;func DeleteAllKeys(storeID string, out io.Writer) error {&#xA;    // Create a &#39;spinner&#39; which helps visually update the user on the progress.&#xA;    spinnerMessage := &amp;quot;Deleting keys&amp;quot;&#xA;    var spinner text.Spinner&#xA;&#xA;    var err error&#xA;    spinner, err = text.NewSpinner(out)&#xA;    if err != nil {&#xA;        return err&#xA;    }&#xA;    err = spinner.Start()&#xA;    if err != nil {&#xA;        return err&#xA;    }&#xA;    spinner.Message(spinnerMessage + &amp;quot;...&amp;quot;)&#xA;&#xA;    // Create a keys paginator.&#xA;    p := fastly.NewListKVStoreKeysPaginator(&amp;amp;fastly.ListKVStoreKeysInput{&#xA;        StoreID: storeID,&#xA;    })&#xA;&#xA;    // Channel for tracking errors when deleting keys.&#xA;    errorsCh := make(chan string, MaxErrors)&#xA;    &#xA;    // Channel for tracking keys to delete.&#xA;    keysCh := make(chan string, 1000) // this number correlates to the pagination &#xA;                                      // page size defined by the API&#xA;&#xA;    var (&#xA;        // Track the number of keys deleted.&#xA;        deleteCount atomic.Uint64&#xA;        &#xA;        // Track which keys failed to be deleted.&#xA;        failedKeys []string&#xA;        &#xA;        // This will help us wait for all goroutines to complete.&#xA;        wg sync.WaitGroup&#xA;    )&#xA;&#xA;    // We have two separate execution flows happening at once:&#xA;    //&#xA;    // 1. Pushing keys from pagination data into a key channel.&#xA;    // 2. Pulling keys from key channel and issuing API DELETE call.&#xA;    //&#xA;    // We have a limit on the number of errors. Once that limit is reached we&#39;ll&#xA;    // stop the second set of goroutines processing the delete operation.&#xA;&#xA;    wg.Add(1)&#xA;    go func() {&#xA;        defer wg.Done()&#xA;        defer close(keysCh)&#xA;        for p.Next() {&#xA;            for _, key := range p.Keys() {&#xA;                keysCh &amp;lt;- key&#xA;            }&#xA;        }&#xA;    }()&#xA;&#xA;    // Limit the number of goroutines spun up to the specified pool size.&#xA;    for range PoolSize {&#xA;        wg.Add(1)&#xA;        go func() {&#xA;            defer wg.Done()&#xA;            for key := range keysCh {&#xA;                err := fastly.DeleteKVStoreKey(&#xA;                    &amp;amp;fastly.DeleteKVStoreKeyInput{StoreID: c.StoreID, Key: key},&#xA;                )&#xA;                if err != nil {&#xA;                    select {&#xA;                    case errorsCh &amp;lt;- key:&#xA;                    default:&#xA;                        return // channel is full (i.e. MaxErrors limit reached)&#xA;                    }&#xA;                }&#xA;                // Update the TUI (Terminal UI) to reflect the current number of &#xA;                // deleted keys.&#xA;                f := strconv.FormatUint(deleteCount.Add(1), 10)&#xA;                spinner.Message(spinnerMessage + &amp;quot;...&amp;quot; + f)&#xA;            }&#xA;        }()&#xA;    }&#xA;&#xA;    wg.Wait()&#xA;&#xA;    close(errorsCh)&#xA;    for err := range errorsCh {&#xA;        failedKeys = append(failedKeys, err)&#xA;    }&#xA;&#xA;    spinnerMessage = &amp;quot;Deleted keys: &amp;quot; + strconv.FormatUint(deleteCount.Load(), 10)&#xA;&#xA;    if len(failedKeys) &amp;gt; 0 {&#xA;        spinner.StopFailMessage(spinnerMessage)&#xA;        err := spinner.StopFail()&#xA;        if err != nil {&#xA;            return fmt.Errorf(&amp;quot;failed to stop spinner: %w&amp;quot;, err)&#xA;        }&#xA;        return fmt.Errorf(&amp;quot;failed to delete %d keys&amp;quot;, len(failedKeys))&#xA;    }&#xA;&#xA;    spinner.StopMessage(spinnerMessage)&#xA;    if err := spinner.Stop(); err != nil {&#xA;        return fmt.Errorf(&amp;quot;failed to stop spinner: %w&amp;quot;, err)&#xA;    }&#xA;&#xA;    text.Success(out, &amp;quot;\nDeleted all keys from KV Store &#39;%s&#39;&amp;quot;, c.StoreID)&#xA;    return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So you can see we have multiple goroutines spun up (and we wait for them using&#xA;&lt;code&gt;sync.WaitGroup&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The first goroutine is iterating over the pagination data and pushing data&#xA;into a channel.&lt;/li&gt;&#xA;&lt;li&gt;The other goroutines (we have a limit of &lt;code&gt;PoolSize&lt;/code&gt;) are pulling data from the&#xA;channel and issuing key deletion API calls.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We also use the &lt;code&gt;select&lt;/code&gt; statement to control whether we stop the goroutines&#xA;processing the deletion operations. The way we do this is to define another&#xA;channel (&lt;code&gt;errorsCh&lt;/code&gt;) with a buffer size of &lt;code&gt;MaxErrors&lt;/code&gt;, and then every time we&#xA;get an error we push the error into that channel. If the channel becomes full&#xA;(which it will do eventually because there&amp;rsquo;s nothing pulling messages from the&#xA;&lt;code&gt;errorsCh&lt;/code&gt; channel), then the &lt;code&gt;select&lt;/code&gt; statement will fallthrough to its&#xA;&lt;code&gt;default&lt;/code&gt; block and we&amp;rsquo;ll return the goroutine (causing it to stop running)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The last interesting concurrency primitive we use is &lt;code&gt;atomic.Uint64&lt;/code&gt; for&#xA;accurately tracking the number of deleted keys. We use its &lt;code&gt;Add()&lt;/code&gt; method within&#xA;the goroutine to safely increment the counter, and then at the end of the&#xA;function we use its &lt;code&gt;Load()&lt;/code&gt; method to safely extract the final value.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;update-2024-11-01&#34;&gt;UPDATE 2024.11.01&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Below is a modification to the &amp;lsquo;real world&amp;rsquo; example code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The difference is in how errors are handled. In the original code we would stop&#xA;processing the deletion of keys when an error threshold was reached. But in the&#xA;following version we don&amp;rsquo;t want that to happen. Instead we want to &lt;em&gt;keep&lt;/em&gt;&#xA;processing errors, but that introduces a new challenge related to channel buffer&#xA;size (e.g. we can&amp;rsquo;t set an infinite amount of memory for a channel) and so at&#xA;some point the errors channel is going to get filled up and we need to decide&#xA;what to do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case we can realistically only drop errors. But we can alleviate that a&#xA;little bit by trying to pull messages out from the errors channel and appending&#xA;them to the &lt;code&gt;failedKeys&lt;/code&gt; slice concurrently. This will make space in the&#xA;channel&amp;rsquo;s buffer and so we can push more errors into it if they occur.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with pulling errors out of the errors channel concurrently is we&#xA;need to &lt;code&gt;range&lt;/code&gt; over the channel, but that will cause a deadlock if we don&amp;rsquo;t&#xA;handle it correctly (because ranging over a channel only terminates the loop&#xA;when the channel is closed). So we need to introduce not one &lt;code&gt;sync.WaitGroup&lt;/code&gt;&#xA;but &lt;em&gt;two&lt;/em&gt;! See the code comments below for more details&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;!-- markdownlint-disable --&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// deleteAllKVStoreKeys deletes all keys within the specified KV Store.&#xA;func deleteAllKVStoreKeys(&#xA;    conn *gofastly.Client, &#xA;    storeID string, &#xA;    maxErrors, poolSize int&#xA;) error {&#xA;    p := conn.NewListKVStoreKeysPaginator(&amp;amp;fastly.ListKVStoreKeysInput{&#xA;        StoreID: storeID,&#xA;    })&#xA;&#xA;    errorsCh := make(chan string, maxErrors)&#xA;    keysCh := make(chan string, 1000) // number correlates to pagination page size&#xA;&#xA;    var (&#xA;        failedKeys   []string&#xA;        mu           sync.Mutex&#xA;        wgProcessing sync.WaitGroup&#xA;        wgErrorCh    sync.WaitGroup&#xA;    )&#xA;&#xA;    // We have three separate execution flows happening at once:&#xA;    //&#xA;    // 1. Pushing keys from pagination data into a key channel.&#xA;    // 2. Pulling keys from error channel and appending to failedKeys slice.&#xA;    // 3. Pulling keys from key channel and issuing API DELETE call.&#xA;    //&#xA;    // The second item is problematic, in that ranging over a channel only&#xA;    // terminates when the channel is closed. So we need to ensure we close the&#xA;    // errorsCh once we&#39;ve finished processing the deletion of all the keys.&#xA;    //&#xA;    // To do that we need two sets of wait groups.&#xA;    //&#xA;    // The first is wgProcessing which keeps track of all goroutines related to&#xA;    // processing the pagination data (e.g. the goroutine ranging over the&#xA;    // paginator keys, and the goroutine ranging over the keysCh as part of the&#xA;    // poolSize loop).&#xA;    //&#xA;    // The second wait group is wgErrorCh which tracks when the first&#xA;    // (wgProcessing) has completed and then closes errorsCh.&#xA;&#xA;    // The following goroutine finishes once all pagination keys have been&#xA;    // processed.&#xA;    wgProcessing.Add(1)&#xA;    go func() {&#xA;        defer wgProcessing.Done()&#xA;        defer close(keysCh)&#xA;        for p.Next() {&#xA;            for _, key := range p.Keys() {&#xA;                keysCh &amp;lt;- key&#xA;            }&#xA;        }&#xA;    }()&#xA;&#xA;    // The following goroutine finishes once the errorsCh is closed.&#xA;    wgErrorCh.Add(1)&#xA;    go func() {&#xA;        defer wgErrorCh.Done()&#xA;        for err := range errorsCh {&#xA;            mu.Lock()&#xA;            failedKeys = append(failedKeys, err)&#xA;            mu.Unlock()&#xA;        }&#xA;    }()&#xA;&#xA;    // The following goroutines close once they&#39;ve pulled all data from keysCh.&#xA;    for i := 1; i &amp;lt;= poolSize; i++ {&#xA;        wgProcessing.Add(1)&#xA;        go func() {&#xA;            defer wgProcessing.Done()&#xA;            for key := range keysCh {&#xA;                err := conn.DeleteKVStoreKey(&#xA;                    &amp;amp;fastly.DeleteKVStoreKeyInput{StoreID: storeID, Key: key},&#xA;                )&#xA;                if err != nil {&#xA;                    select {&#xA;                    case errorsCh &amp;lt;- key:&#xA;                    default:&#xA;                        continue // the larger we make maxErrors &#xA;                                 // the less likely we&#39;ll drop errors &#xA;                                 // (obviously there&#39;s a memory trade-off to be made)&#xA;                    }&#xA;                }&#xA;            }&#xA;        }()&#xA;    }&#xA;&#xA;    // The following goroutine is closed once the &#39;processing&#39; goroutines are&#xA;    // finished.&#xA;    wgErrorCh.Add(1)&#xA;    go func() {&#xA;        defer wgErrorCh.Done()&#xA;        wgProcessing.Wait() // Wait for all deletion and pagination tasks.&#xA;        close(errorsCh)&#xA;    }()&#xA;&#xA;    // Wait for the error-handling goroutines to finish processing.&#xA;    wgErrorCh.Wait()&#xA;&#xA;    if len(failedKeys) &amp;gt; 0 {&#xA;        return fmt.Errorf(&amp;quot;failed to delete %d keys&amp;quot;, len(failedKeys))&#xA;    }&#xA;&#xA;    return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;!-- markdownlint-enable --&gt;&#xA;&#xA;&lt;h3 id=&#34;tls-certificate-asynchronous-pipeline&#34;&gt;TLS Certificate asynchronous Pipeline&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I ended up needing to write some pretty complex asynchronous code with multiple&#xA;layers of fan-out requests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To explain, I was building an API as a thin wrapper around an ACME client for&#xA;issuing TLS certificates and I have an asynchronous pipeline with multiple&#xA;stages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In one stage I have an &amp;lsquo;order&amp;rsquo; which contains multiple &amp;lsquo;authorization&amp;rsquo; objects.&#xA;These objects are essentially each domain that needs to be validated (i.e. the&#xA;server needs to confirm the customer owns the domains).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The server issues multiple challenges for each authorization. There are three&#xA;challenge types: dns, http, tls. The customer just needs to validate one of&#xA;them, but we don&amp;rsquo;t know which one they&amp;rsquo;ll use so we try them all. Hence we need&#xA;to fan-out each challenge request concurrently.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also process the parent authorization (i.e. the domains) concurrently because&#xA;we don&amp;rsquo;t want to sequentially process them as that would take a lot longer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, as an example, if I (as the customer) had made an API request for a new TLS&#xA;certificate that I wanted to have for an apex domain (example.com) and a CNAME&#xA;(www.example.com), then we would:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Have two authorizations (each running concurrently)&lt;/li&gt;&#xA;&lt;li&gt;Each authorization would have three challenges (each running concurrently)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The code for that looks like the following:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;💡 The reason I&amp;rsquo;m sharing this code is because it uses lots of different&#xA;concurrency mechanisms to ensure efficient use of memory resources (i.e. we&#xA;need to ensure goroutines finishes more quickly, and actually get cleaned up&#xA;completely and not leak memory).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;!-- markdownlint-disable --&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package order&#xA;&#xA;import (&#xA;    &amp;quot;context&amp;quot;&#xA;    &amp;quot;errors&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io&amp;quot;&#xA;    &amp;quot;log/slog&amp;quot;&#xA;    &amp;quot;math&amp;quot;&#xA;    &amp;quot;net&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;slices&amp;quot;&#xA;    &amp;quot;strings&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;&#xA;    &amp;quot;github.com/mholt/acmez/v3/acme&amp;quot;&#xA;&#xA;    &amp;quot;github.com/fastly/ascerta/internal/httpx&amp;quot;&#xA;    &amp;quot;github.com/fastly/ascerta/internal/log&amp;quot;&#xA;)&#xA;&#xA;const (&#xA;    // backoffMax is the maximum number to backoff by (i.e. 2 hours in minutes).&#xA;    backoffMax = 120&#xA;    // backoffMultiplier is the multiplier used for exponential backoff.&#xA;    backoffMultiplier = 2&#xA;    // checkTimeout short-circuits an authorization check if it stalls.&#xA;    // We don&#39;t expect an individual check to take longer than 5 seconds.&#xA;    checkTimeout = time.Duration(5) * time.Second&#xA;    // maxRetries is the maximum number of times a message can be re-queued.&#xA;    maxRetries = 10&#xA;)&#xA;&#xA;var (&#xA;    // backoff is the duration to backoff by (in minutes).&#xA;    // This is a variable so it can be updated for exponential backoff purposes.&#xA;    backoff = 5.0&#xA;&#xA;    // supportedChallengeTypes filters unsupported challenge types.&#xA;    supportedChallengeTypes = []string{&#xA;        acme.ChallengeTypeDNS01,&#xA;        acme.ChallengeTypeHTTP01,&#xA;    }&#xA;)&#xA;&#xA;// consumerChecks takes new certificate orders from the queue and determines&#xA;// what pre-flight checks to perform (avoiding bothering a CA unnecessarily).&#xA;func consumerChecks() {&#xA;    l := log.New()&#xA;    ctx := context.Background()&#xA;&#xA;    for o := range ordersCheck {&#xA;        sl := l.With(&#xA;            slog.Group(&amp;quot;retries&amp;quot;,&#xA;                slog.Int(&amp;quot;current&amp;quot;, o.retries),&#xA;                slog.Int(&amp;quot;max&amp;quot;, maxRetries),&#xA;            ),&#xA;        )&#xA;        sl.LogAttrs(ctx, slog.LevelInfo, &amp;quot;consumer_check&amp;quot;, slog.String(&amp;quot;state&amp;quot;, &amp;quot;start&amp;quot;))&#xA;&#xA;        if o.retries &amp;gt; maxRetries {&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;consumer_check&amp;quot;, slog.String(&amp;quot;state&amp;quot;, &amp;quot;dead&amp;quot;))&#xA;            continue&#xA;        }&#xA;&#xA;        // We have one &#39;authorization&#39; per SAN list entry (i.e. per domain).&#xA;        // We then have multiple &#39;challenges&#39; per authorization to check.&#xA;        //&#xA;        // We process each authorization asynchronously.&#xA;        // We also process each authorization&#39;s challenges asynchronously.&#xA;&#xA;        var wg sync.WaitGroup&#xA;&#xA;        for i, a := range o.authorizations {&#xA;            // If an order has been placed back on the queue, then we want to&#xA;            // avoid having to re-validate authorizations that were already&#xA;            // validated successfully.&#xA;            if !a.authorized {&#xA;                wg.Add(1)&#xA;                go func() {&#xA;                    defer wg.Done()&#xA;                    processAuthorization(ctx, l, i, &amp;amp;o)&#xA;                }()&#xA;            }&#xA;        }&#xA;&#xA;        wg.Wait()&#xA;&#xA;        // We now need to check if any authorizations failed.&#xA;        // If so, we need to re-queue the order.&#xA;        var (&#xA;            requeue bool&#xA;            failed  []string&#xA;        )&#xA;        for _, a := range o.authorizations {&#xA;            if !a.authorized {&#xA;                failed = append(failed, a.authorization.IdentifierValue())&#xA;                requeue = true&#xA;            }&#xA;        }&#xA;        if requeue {&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;consumer_check&amp;quot;,&#xA;                slog.Any(&amp;quot;err&amp;quot;, errors.New(&amp;quot;not all authorizations were successful&amp;quot;)),&#xA;                slog.Bool(&amp;quot;retry&amp;quot;, true),&#xA;                slog.Float64(&amp;quot;backoff&amp;quot;, backoff),&#xA;                slog.String(&amp;quot;failed&amp;quot;, strings.Join(failed, &amp;quot;,&amp;quot;)),&#xA;                slog.String(&amp;quot;state&amp;quot;, &amp;quot;re-queued&amp;quot;),&#xA;            )&#xA;            o.retries++&#xA;&#xA;            time.Sleep(time.Duration(backoff) * time.Minute) // increases exponentially&#xA;            backoff = math.Min(backoff*backoffMultiplier, backoffMax)&#xA;            go func() {&#xA;                ordersCheck &amp;lt;- o // put the order back on the queue for retry.&#xA;            }()&#xA;            continue&#xA;        }&#xA;&#xA;        sl.LogAttrs(ctx, slog.LevelInfo, &amp;quot;consumer_check&amp;quot;,&#xA;            slog.Any(&amp;quot;order&amp;quot;, o),&#xA;            slog.String(&amp;quot;state&amp;quot;, &amp;quot;complete&amp;quot;),&#xA;        )&#xA;        ordersValidate &amp;lt;- o&#xA;    }&#xA;}&#xA;&#xA;// processAuthorization processes each authorization concurrently. Each&#xA;// challenge within the authorization is also processed concurrently.&#xA;func processAuthorization(ctx context.Context, l *slog.Logger, i int, o *Order) {&#xA;    a := o.authorizations[i]&#xA;    sl := l.With(slog.String(&amp;quot;authorization&amp;quot;, a.authorization.Identifier.Value))&#xA;&#xA;    // We wait for only one goroutine to complete successfully.&#xA;    authorized := make(chan acme.Challenge, 1)&#xA;&#xA;    // The use of a cancellable context is to short-circuit running goroutines.&#xA;    ctx, cancel := context.WithCancel(ctx)&#xA;    defer cancel()&#xA;&#xA;    // The WaitGroup allows us to verify that all goroutines exit properly.&#xA;    var wg sync.WaitGroup&#xA;&#xA;    for _, c := range a.authorization.Challenges {&#xA;        if slices.Contains(supportedChallengeTypes, c.Type) {&#xA;            wg.Add(1)&#xA;            go func(c acme.Challenge) {&#xA;                defer wg.Done()&#xA;                if err := challengeCheck(ctx, sl, c); err == nil {&#xA;                    // The use of select with a cancellable context allows to&#xA;                    // solve two issues:&#xA;                    //&#xA;                    // 1. Signal goroutines to stop if the channel gets blocked.&#xA;                    //    This can happen if both dns and http challenges pass.&#xA;                    //&#xA;                    // 2. Signal goroutines to stop when one challenge passes.&#xA;                    //    Allowing us to short-circuit more quickly.&#xA;                    //    And avoids waiting for the checkTimeout below.&#xA;                    select {&#xA;                    case &amp;lt;-ctx.Done():&#xA;                    case authorized &amp;lt;- c:&#xA;                    }&#xA;                }&#xA;            }(c)&#xA;        }&#xA;    }&#xA;&#xA;    // Block until one of the challenges returns successfully.&#xA;    // Otherwise we&#39;ll timeout and cause a re-queue.&#xA;    select {&#xA;    case c := &amp;lt;-authorized:&#xA;        cancel()  // short-circuit any still running goroutines.&#xA;        wg.Wait() // validate we&#39;ve cleaned up all goroutines.&#xA;        sl.LogAttrs(ctx, slog.LevelInfo, &amp;quot;authorization_check&amp;quot;,&#xA;            slog.Bool(&amp;quot;success&amp;quot;, true),&#xA;            slog.Int(&amp;quot;index&amp;quot;, i),&#xA;            slog.String(&amp;quot;validation_method&amp;quot;, c.Type),&#xA;        )&#xA;        o.authorizations[i].authorized = true&#xA;        o.authorizations[i].challengeType = c.Type&#xA;    case &amp;lt;-time.After(checkTimeout): // in case no challenges are valid&#xA;        cancel()  // short-circuit any still running goroutines.&#xA;        wg.Wait() // validate we&#39;ve cleaned up all goroutines.&#xA;        sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;authorization_check&amp;quot;, slog.String(&amp;quot;reason&amp;quot;, &amp;quot;timeout&amp;quot;))&#xA;    }&#xA;}&#xA;&#xA;// challengeCheck identifies the challenge type and triggers that check.&#xA;func challengeCheck(ctx context.Context, l *slog.Logger, c acme.Challenge) error {&#xA;    switch c.Type {&#xA;    case acme.ChallengeTypeDNS01:&#xA;        return checkDNS(ctx, l, c)&#xA;    case acme.ChallengeTypeHTTP01:&#xA;        return checkHTTP(ctx, l, c)&#xA;    }&#xA;    return nil&#xA;}&#xA;&#xA;// checkDNS looks up the TXT record to see if it contains the correct value. It&#xA;// will return nil if the record exists with the correct value.&#xA;func checkDNS(ctx context.Context, l *slog.Logger, c acme.Challenge) error {&#xA;    // use a resolver to propagate context&#xA;    var r net.Resolver&#xA;    txtRecords, err := r.LookupTXT(ctx, c.DNS01TXTRecordName())&#xA;    if err != nil {&#xA;        err := fmt.Errorf(&amp;quot;failed to lookup TXT record: %w&amp;quot;, err)&#xA;        l.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_dns&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, err))&#xA;        return err&#xA;    }&#xA;    if slices.Contains(txtRecords, c.DNS01KeyAuthorization()) {&#xA;        return nil&#xA;    }&#xA;    err = fmt.Errorf(&amp;quot;record exists but does not contain correct value: %s&amp;quot;, strings.Join(txtRecords, &amp;quot;,&amp;quot;))&#xA;    l.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_dns&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, err))&#xA;    return err&#xA;}&#xA;&#xA;// checkHTTP looks up the .well-known/acme-challenge/... path to see if it&#xA;// exists at that path location and will return nil if it does.&#xA;func checkHTTP(ctx context.Context, l *slog.Logger, c acme.Challenge) error {&#xA;    var lastErr error&#xA;&#xA;    for _, protocol := range []string{&amp;quot;http&amp;quot;, &amp;quot;https&amp;quot;} {&#xA;        endpoint := fmt.Sprintf(&amp;quot;%s://%s%s&amp;quot;, protocol, c.Identifier.Value, c.HTTP01ResourcePath())&#xA;        sl := l.With(slog.String(&amp;quot;endpoint&amp;quot;, endpoint))&#xA;&#xA;        req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)&#xA;        if err != nil {&#xA;            lastErr = fmt.Errorf(&amp;quot;failed to create a http.Request for &#39;%s&#39;: %w&amp;quot;, endpoint, err)&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, lastErr))&#xA;            continue&#xA;        }&#xA;&#xA;        res, err := httpx.Client.Do(req)&#xA;        if err != nil {&#xA;            // Checking context cancelled allows us to return faster.&#xA;            // i.e. we&#39;re either already authorized or we timed out.&#xA;            if errors.Is(err, context.Canceled) {&#xA;                err := fmt.Errorf(&amp;quot;failed to send http.Request: %w&amp;quot;, ctx.Err())&#xA;                sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, err))&#xA;                return err&#xA;            }&#xA;            lastErr = fmt.Errorf(&amp;quot;failed to send http.Request: %w&amp;quot;, err)&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, lastErr))&#xA;            continue&#xA;        }&#xA;&#xA;        // NOTE: It&#39;s unsafe to defer inside a loop so I manually close res.Body&#xA;        if res.StatusCode != http.StatusOK {&#xA;            res.Body.Close()&#xA;            lastErr = fmt.Errorf(&amp;quot;invalid http status &#39;%s&#39;&amp;quot;, res.Status)&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, lastErr))&#xA;            continue&#xA;        }&#xA;&#xA;        body, err := io.ReadAll(res.Body)&#xA;        if err != nil {&#xA;            res.Body.Close()&#xA;            lastErr = fmt.Errorf(&amp;quot;failed to read response body: %w&amp;quot;, err)&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, lastErr))&#xA;            continue&#xA;        }&#xA;        res.Body.Close()&#xA;&#xA;        if string(body) != c.KeyAuthorization {&#xA;            lastErr = fmt.Errorf(&amp;quot;invalid response body &#39;%s&#39;: expected &#39;%s&#39;&amp;quot;, body, c.KeyAuthorization)&#xA;            sl.LogAttrs(ctx, slog.LevelWarn, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, lastErr))&#xA;            continue&#xA;        }&#xA;&#xA;        return nil // success&#xA;    }&#xA;&#xA;    if lastErr != nil {&#xA;        return lastErr&#xA;    }&#xA;&#xA;    // WARNING: We should never reach this part of the code.&#xA;    // We should have already returned a success or tracked an error.&#xA;    err := errors.New(&amp;quot;unexpected code path reached&amp;quot;)&#xA;    l.LogAttrs(ctx, slog.LevelError, &amp;quot;check_http&amp;quot;, slog.Any(&amp;quot;err&amp;quot;, err))&#xA;    return err&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;processAuthorization&lt;/code&gt; function specifically might look over engineered but&#xA;it&amp;rsquo;s critical that we don&amp;rsquo;t have goroutines hanging around waiting to be&#xA;unblocked. So all these concurrency mechanisms are in place to ensure the code&#xA;is as robust as possible.&lt;/p&gt;&#xA;&#xA;&lt;!-- markdownlint-enable --&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-material&#34;&gt;Reference Material&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;../go-style-guide/index.html&#34;&gt;Go Style Guide&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://go.dev/doc/effective_go#concurrency&#34; target=&#34;_blank&#34;&gt;go.dev/doc/effective_go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-concurrency-patterns/</guid>
      <link>https://www.integralist.co.uk/posts/go-concurrency-patterns/</link>
      <pubDate>Fri, 15 Nov 2024 00:00:00 +0000</pubDate>
      <title>Go Concurrency Patterns</title>
    </item>
    <item>
      <description>&lt;p&gt;In the below Go file we use bitwise operators to manipulate individual flags (on/off switches) in a single integer, where each bit position represents a different status.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First we&amp;rsquo;ll look at the code, and then we&amp;rsquo;ll explain how it works:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;strings&amp;quot;&#xA;)&#xA;&#xA;// Define bit flags as constants, where each status is represented by a unique bit position&#xA;const (&#xA;    StatusActive   = 1 &amp;lt;&amp;lt; iota // 1 &amp;lt;&amp;lt; 0 which is 0001 (binary)&#xA;    StatusAdmin                // 1 &amp;lt;&amp;lt; 1 which is 0010&#xA;    StatusBanned               // 1 &amp;lt;&amp;lt; 2 which is 0100&#xA;    StatusVerified             // 1 &amp;lt;&amp;lt; 3 which is 1000&#xA;)&#xA;&#xA;// Stringify statuses for easier output&#xA;func stringifyStatus(status int) string {&#xA;    statuses := []string{}&#xA;&#xA;    if status&amp;amp;StatusActive != 0 {&#xA;        statuses = append(statuses, &amp;quot;Active&amp;quot;)&#xA;    }&#xA;    if status&amp;amp;StatusAdmin != 0 {&#xA;        statuses = append(statuses, &amp;quot;Admin&amp;quot;)&#xA;    }&#xA;    if status&amp;amp;StatusBanned != 0 {&#xA;        statuses = append(statuses, &amp;quot;Banned&amp;quot;)&#xA;    }&#xA;    if status&amp;amp;StatusVerified != 0 {&#xA;        statuses = append(statuses, &amp;quot;Verified&amp;quot;)&#xA;    }&#xA;&#xA;    return strings.Join(statuses, &amp;quot;, &amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;    // Let&#39;s create a user status and use bitwise OR to combine different flags&#xA;&#xA;    var userStatus int&#xA;&#xA;    // Set the user as active and verified&#xA;    userStatus |= StatusActive | StatusVerified&#xA;    fmt.Println(&amp;quot;Initial Status:&amp;quot;, stringifyStatus(userStatus))&#xA;&#xA;    // Add &amp;quot;Admin&amp;quot; status&#xA;    userStatus |= StatusAdmin&#xA;    fmt.Println(&amp;quot;After adding Admin:&amp;quot;, stringifyStatus(userStatus))&#xA;&#xA;    // Remove &amp;quot;Verified&amp;quot; status using bitwise AND with NOT&#xA;    userStatus &amp;amp;^= StatusVerified&#xA;    fmt.Println(&amp;quot;After removing Verified:&amp;quot;, stringifyStatus(userStatus))&#xA;&#xA;    // Add &amp;quot;Banned&amp;quot; status&#xA;    userStatus |= StatusBanned&#xA;    fmt.Println(&amp;quot;After adding Banned:&amp;quot;, stringifyStatus(userStatus))&#xA;&#xA;    // Check if the user is an admin&#xA;    if userStatus&amp;amp;StatusAdmin != 0 {&#xA;        fmt.Println(&amp;quot;User is an admin.&amp;quot;)&#xA;    } else {&#xA;        fmt.Println(&amp;quot;User is NOT an admin.&amp;quot;)&#xA;    }&#xA;&#xA;    // Remove &amp;quot;Admin&amp;quot; status using bitwise AND with NOT&#xA;    userStatus &amp;amp;^= StatusAdmin&#xA;    fmt.Println(&amp;quot;After removing Admin:&amp;quot;, stringifyStatus(userStatus))&#xA;&#xA;    // Check if the user is banned&#xA;    if userStatus&amp;amp;StatusBanned != 0 {&#xA;        fmt.Println(&amp;quot;User is banned.&amp;quot;)&#xA;    } else {&#xA;        fmt.Println(&amp;quot;User is NOT banned.&amp;quot;)&#xA;    }&#xA;&#xA;    // Check if the user is an admin&#xA;    if userStatus&amp;amp;StatusAdmin != 0 {&#xA;        fmt.Println(&amp;quot;User is an admin.&amp;quot;)&#xA;    } else {&#xA;        fmt.Println(&amp;quot;User is NOT an admin.&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;visualising-bits&#34;&gt;Visualising Bits&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In case you need a reminder of a what bit alignment and shifting look like:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/bits-visualised.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/bits-visualised.png&#34; alt=&#34;bits visualised&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;defining-bit-flags&#34;&gt;Defining Bit Flags&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each status is assigned a unique power of 2 using bit shifting (&lt;code&gt;1 &amp;lt;&amp;lt; iota&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This ensures each flag only affects a single bit:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;StatusActive&lt;/code&gt; has the binary value &lt;code&gt;0001&lt;/code&gt; (&lt;code&gt;1 &amp;lt;&amp;lt; 0&lt;/code&gt; == 1 in decimal).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;StatusAdmin&lt;/code&gt; has the binary value &lt;code&gt;0010&lt;/code&gt; (&lt;code&gt;1 &amp;lt;&amp;lt; 1&lt;/code&gt; == 2 in decimal).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;StatusBanned&lt;/code&gt; has the binary value &lt;code&gt;0100&lt;/code&gt; (&lt;code&gt;1 &amp;lt;&amp;lt; 2&lt;/code&gt; == 4 in decimal).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;StatusVerified&lt;/code&gt; has the binary value &lt;code&gt;1000&lt;/code&gt; (&lt;code&gt;1 &amp;lt;&amp;lt; 3&lt;/code&gt; == 8 in decimal).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;setting-statuses&#34;&gt;Setting Statuses&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following example combines two separate status flags:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;userStatus |= StatusActive | StatusVerified&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In binary, this results in &lt;code&gt;1001&lt;/code&gt; (or 9 in decimal), which means both the &amp;ldquo;active&amp;rdquo; and &amp;ldquo;verified&amp;rdquo; flags are set.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;adding-and-removing-flags&#34;&gt;Adding and Removing Flags&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following example sets the &amp;ldquo;admin&amp;rdquo; bit without affecting the other bits, resulting in &lt;code&gt;1011&lt;/code&gt; (11 in decimal):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;userStatus |= StatusAdmin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;comparing-statuses&#34;&gt;Comparing Statuses&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Once &lt;code&gt;userStatus&lt;/code&gt; has combined flags we can use the &lt;code&gt;&amp;amp;&lt;/code&gt; operator to perform a bitwise &lt;code&gt;AND&lt;/code&gt; operation, which means it compares each bit of two integers. For each bit position, if both bits are 1, the result at that position will be 1; otherwise, it will be 0.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what happens when we compare &lt;code&gt;userStatus&amp;amp;StatusAdmin != 0&lt;/code&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, &lt;code&gt;StatusAdmin&lt;/code&gt; is a bit flag defined as &lt;code&gt;1 &amp;lt;&amp;lt; 1&lt;/code&gt;, which results in &lt;code&gt;0010&lt;/code&gt; in binary. This means that &lt;code&gt;StatusAdmin&lt;/code&gt; occupies the second bit position in the binary representation of an integer. When we do &lt;code&gt;userStatus&amp;amp;StatusAdmin&lt;/code&gt;, we&amp;rsquo;re effectively &amp;ldquo;masking&amp;rdquo; all bits except for the one represented by StatusAdmin (this is known as &lt;strong&gt;bit masking&lt;/strong&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we perform &lt;code&gt;userStatus&amp;amp;StatusAdmin&lt;/code&gt;, we get a result where only the bit corresponding to &lt;code&gt;StatusAdmin&lt;/code&gt; remains (and is set to &lt;code&gt;1&lt;/code&gt; if that bit was already set in &lt;code&gt;userStatus&lt;/code&gt;). If this result is non-zero (&lt;code&gt;!= 0&lt;/code&gt;), it means the &lt;code&gt;StatusAdmin&lt;/code&gt; bit is set in &lt;code&gt;userStatus&lt;/code&gt;. If it&amp;rsquo;s zero, then &lt;code&gt;StatusAdmin&lt;/code&gt; is not set in &lt;code&gt;userStatus&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at the code in &lt;code&gt;bitwise.go&lt;/code&gt; we&amp;rsquo;ll see &lt;code&gt;userStatus&lt;/code&gt; is initially set to include &lt;code&gt;StatusActive&lt;/code&gt; and &lt;code&gt;StatusVerified&lt;/code&gt;, so &lt;code&gt;userStatus&lt;/code&gt; is &lt;code&gt;1001&lt;/code&gt; in binary (which is &lt;code&gt;9&lt;/code&gt; in decimal). Remember &lt;code&gt;StatusActive&lt;/code&gt; occupied the first bit position (&lt;code&gt;0001&lt;/code&gt;), while &lt;code&gt;StatusVerified&lt;/code&gt; occupied the fourth bit position (&lt;code&gt;1000&lt;/code&gt;) so if setting both flags we get the combined &lt;code&gt;1001&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, we add the &lt;code&gt;StatusAdmin&lt;/code&gt; flag with &lt;code&gt;userStatus |= StatusAdmin&lt;/code&gt;, making &lt;code&gt;userStatus&lt;/code&gt; now &lt;code&gt;1011&lt;/code&gt; in binary (which is 11 in decimal). When we check if &lt;code&gt;StatusAdmin&lt;/code&gt; is set using &lt;code&gt;userStatus&amp;amp;StatusAdmin != 0&lt;/code&gt; we get back &lt;code&gt;2&lt;/code&gt; from &lt;code&gt;userStatus&amp;amp;StatusAdmin&lt;/code&gt; (which is &lt;code&gt;0010&lt;/code&gt; in binary) because we&amp;rsquo;ve bit masked the other bits that might have been turned on (if you recall, using &lt;code&gt;&amp;amp;&lt;/code&gt; turns each bit to zero except for those bits that were 1 in both numbers being compared), in order to &lt;em&gt;reveal&lt;/em&gt; whether the &lt;code&gt;StatusAdmin&lt;/code&gt; bit was set on or not (i.e. &lt;code&gt;0&lt;/code&gt; != &lt;code&gt;2&lt;/code&gt; so we know this person is an admin).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/bitwise-operations-in-go/</guid>
      <link>https://www.integralist.co.uk/posts/bitwise-operations-in-go/</link>
      <pubDate>Sun, 10 Nov 2024 00:00:00 +0000</pubDate>
      <title>Bitwise Operations in Go</title>
    </item>
    <item>
      <description>&lt;p&gt;So you&amp;rsquo;ve heard about computing at the edge, and you&amp;rsquo;ve heard that &lt;a href=&#34;https://www.fastly.com/documentation/developers/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt;&#xA;let&amp;rsquo;s you run JavaScript, Go, Rust and &lt;a href=&#34;https://www.fastly.com/documentation/guides/compute/custom/&#34; target=&#34;_blank&#34;&gt;any other language&lt;/a&gt; that compiles to&#xA;Wasm at the edge&amp;hellip; well, let&amp;rsquo;s take a look and while we&amp;rsquo;re at it let&amp;rsquo;s try and&#xA;understand how caching works there too.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;getting-started&#34;&gt;Getting started&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, first thing you&amp;rsquo;re going to need is a &lt;a href=&#34;https://www.fastly.com/signup/&#34; target=&#34;_blank&#34;&gt;fastly account&lt;/a&gt; so follow the link&#xA;and sign up for FREE (for more details see &lt;a href=&#34;https://www.fastly.com/pricing/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Fastly has recently updated its &lt;a href=&#34;https://manage.fastly.com/&#34; target=&#34;_blank&#34;&gt;UI&lt;/a&gt; to make creating a new&#xA;Compute service even easier by providing a step through wizard-style&#xA;experience to set up and configure a new service (go check it out).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next you&amp;rsquo;re going to need the &lt;a href=&#34;https://www.fastly.com/documentation/reference/tools/cli/&#34; target=&#34;_blank&#34;&gt;Fastly CLI&lt;/a&gt; to make interacting with Fastly&amp;rsquo;s&#xA;services and products much more efficient, so again, follow the link and get it&#xA;installed, or you can clone the &lt;a href=&#34;https://github.com/fastly/cli&#34; target=&#34;_blank&#34;&gt;public repo&lt;/a&gt; and run &lt;code&gt;make install&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When running the CLI you&amp;rsquo;ll need an API token so you can either generate a token&#xA;via the &lt;a href=&#34;https://manage.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly UI&lt;/a&gt; and then copy/paste it into the CLI using the following&#xA;command (where it will prompt you to enter the token):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly profile create&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or you can use SSO (Single Sign-On) to automatically generate a short-lived&#xA;token that is automatically assigned to the CLI profile (and the token will be&#xA;refreshed automatically when it expires &lt;code&gt;:chef-kiss:&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly profile create --sso&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make sure the CLI is set up correctly, run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly whoami&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;create-a-new-compute-project&#34;&gt;Create a new Compute project&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A Compute project is a directory that contains your service/application code +&#xA;some configuration files required by the CLI to build a Compute &amp;lsquo;package&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A Compute package is a &lt;code&gt;.tar.gz&lt;/code&gt; file containing a &lt;code&gt;main.wasm&lt;/code&gt; binary and a&#xA;&lt;a href=&#34;https://www.fastly.com/documentation/reference/compute/fastly-toml/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;fastly.toml&lt;/code&gt; manifest file&lt;/a&gt;. The CLI handles the creation of the package, and&#xA;even the initial service/application code generation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To create a new package you can run the following command, which will prompt you&#xA;for all the information, such as what language you want to use and which Fastly&#xA;&lt;a href=&#34;https://docs.fastly.com/en/guides/working-with-compute-services#creating-a-new-compute-service&#34; target=&#34;_blank&#34;&gt;starter kit&lt;/a&gt; should be used as the basis for your application code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly compute init&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or if you know what language you want to use, then you can avoid all the prompts&#xA;and let the CLI choose the &amp;lsquo;default&amp;rsquo; starter kit using the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly compute init --language go --non-interactive&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above command selects Go as the language I want to use for building my&#xA;compute service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; subcommand is going to generate the following files:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;.&#xA;├── README.md&#xA;├── fastly.toml&#xA;├── go.mod&#xA;├── go.sum&#xA;└── main.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The only file here that will likely need explaining is the &lt;a href=&#34;https://www.fastly.com/documentation/reference/compute/fastly-toml/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;fastly.toml&lt;/code&gt;&#xA;manifest&lt;/a&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-toml&#34;&gt;authors = [&amp;quot;&amp;quot;]&#xA;cloned_from = &amp;quot;https://github.com/fastly/compute-starter-kit-go-default&amp;quot;&#xA;description = &amp;quot;&amp;quot;&#xA;language = &amp;quot;go&amp;quot;&#xA;manifest_version = 3&#xA;name = &amp;quot;example&amp;quot;&#xA;service_id = &amp;quot;&amp;quot;&#xA;&#xA;[scripts]&#xA;  build = &amp;quot;go build -o bin/main.wasm .&amp;quot;&#xA;  env_vars = [&amp;quot;GOARCH=wasm&amp;quot;, &amp;quot;GOOS=wasip1&amp;quot;]&#xA;  post_init = &amp;quot;go get github.com/fastly/compute-sdk-go@latest&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Compute packages are configured using this &lt;code&gt;fastly.toml&lt;/code&gt; file in the root of the&#xA;project directory tree. This file specifies configuration metadata related to a&#xA;variety of tasks:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Attribution of the package (e.g., name, author)&lt;/li&gt;&#xA;&lt;li&gt;Information required by the CLI to compile and upload it to a compatible&#xA;Fastly service&lt;/li&gt;&#xA;&lt;li&gt;Configuration of local server environments&lt;/li&gt;&#xA;&lt;li&gt;Bootstrapping of service configuration&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll explain more, but for now let&amp;rsquo;s run our project locally so we can see it&#xA;working&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;run-your-code-locally&#34;&gt;Run your code locally&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At this point we can actually run our project locally without even having to&#xA;deploy it!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Running the following command, will compile your project, create a package, and&#xA;pass the package to a local server environment called &lt;a href=&#34;https://github.com/fastly/viceroy&#34; target=&#34;_blank&#34;&gt;Viceroy&lt;/a&gt; which runs&#xA;your package and exposes a local web server for you to interact with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly compute serve&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you want to iteratively develop your application then you can&#xA;pass the &lt;code&gt;--watch&lt;/code&gt; flag to have the CLI monitor your files for changes and to&#xA;hot reload your application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;[!TIP]&#xA;If you want to configure files to be ignored then create a&#xA;&lt;code&gt;.fastlyignore&lt;/code&gt; file. It works like &lt;code&gt;.gitignore&lt;/code&gt; so should be familiar to you.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You should see CLI output that looks a bit like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ fastly compute serve&#xA;&#xA;✓ Verifying fastly.toml&#xA;✓ Identifying package name&#xA;✓ Identifying toolchain&#xA;✓ Running [scripts.build]&#xA;✓ Creating package archive&#xA;&#xA;SUCCESS: Built package (pkg/example.tar.gz)&#xA;&#xA;✓ Running local server&#xA;&#xA;INFO: Command output:&#xA;--------------------------------------------------------------------------------&#xA;2024-06-12T09:51:25.191538Z  WARN no backend definitions found in /private/tmp/example/fastly.toml&#xA;2024-06-12T09:51:25.191658Z  INFO Listening on http://127.0.0.1:7676&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Opening &lt;code&gt;http://127.0.0.1:7676&lt;/code&gt; in your web browser should show the result of&#xA;running the &lt;a href=&#34;https://github.com/fastly/compute-starter-kit-go-default&#34; target=&#34;_blank&#34;&gt;Go default starter kit&lt;/a&gt; code, which generates an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;&#xA;loading a Fastly hosted welcome page.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;sending-requests-to-an-origin-server&#34;&gt;Sending requests to an origin server&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so let&amp;rsquo;s open up the &lt;code&gt;main.go&lt;/code&gt; and delete all the code and replace it with&#xA;the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;context&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;&#xA;    &amp;quot;github.com/fastly/compute-sdk-go/fsthttp&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {&#xA;        r.Header.Add(&amp;quot;TheTime&amp;quot;, time.Now().String())&#xA;        r.CacheOptions.TTL = 30 &#xA;&#xA;        resp, err := r.Send(ctx, &amp;quot;httpme&amp;quot;)&#xA;        if err != nil {&#xA;            w.WriteHeader(fsthttp.StatusBadGateway)&#xA;            fmt.Fprintln(w, err.Error())&#xA;            return&#xA;        }&#xA;&#xA;        resp.Header.Set(&amp;quot;Cache-Control&amp;quot;, &amp;quot;public, s-maxage=86400&amp;quot;)&#xA;        w.Header().Reset(resp.Header)&#xA;        w.WriteHeader(resp.StatusCode)&#xA;        io.Copy(w, resp.Body)&#xA;    })&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;fsthttp.ServeFunc&lt;/code&gt; essentially sets up a listener for incoming requests and&#xA;the given function is the request handler. Inside the request handler we do the&#xA;following things:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Add a HTTP header to the incoming request object:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;r.Header.Add(&amp;quot;TheTime&amp;quot;, time.Now().String())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Override the HTTP caching behaviour of the &lt;em&gt;response&lt;/em&gt; (I&amp;rsquo;ll come back to&#xA;this):&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;r.CacheOptions.TTL = 30&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Forward the request to a &amp;lsquo;backend&amp;rsquo; called &lt;code&gt;httpme&lt;/code&gt; (again, we&amp;rsquo;ll come back to&#xA;this):&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;r.Send(ctx, &amp;quot;httpme&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Set (and possibly override) the &lt;code&gt;Cache-Control&lt;/code&gt; HTTP header on the response:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;resp.Header.Set(&amp;quot;Cache-Control&amp;quot;, &amp;quot;public, max-age=60&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Copy all of the response headers from the backend to the user&amp;rsquo;s response:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;w.Header().Reset(resp.Header)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Send an appropriate response status code:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;w.WriteHeader(resp.StatusCode)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Start &lt;em&gt;streaming&lt;/em&gt; the backend response body to the user:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;&#xA;io.Copy(w, resp.Body)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;OK, so there were two things we need to get a better grip on:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Fastly backends&lt;/li&gt;&#xA;&lt;li&gt;Fastly caching behaviour&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s get into it&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-backends&#34;&gt;Fastly backends&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A backend is something that needs to be defined explicitly, it&amp;rsquo;s an origin&#xA;server owned and managed by you. For example, you might have an API service that&#xA;you want your Compute service/application to communicate with to get data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To define a backend we need to first create one within our Compute service. We&#xA;can do this in many ways (e.g. the Fastly UI, the Fastly API or the Fastly CLI).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For simplicity we&amp;rsquo;re going to use the &lt;code&gt;fastly.toml&lt;/code&gt; manifest file to configure a&#xA;backend, that will be created when we come to deploy our Compute&#xA;service/application for the first time. We&amp;rsquo;ll also use the manifest file to&#xA;configure a backend that will be used when running our Compute&#xA;service/application locally, because we might want to use a mock backend&#xA;locally (although for our case we&amp;rsquo;ll use the same production backend).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Add the following to your &lt;code&gt;fastly.toml&lt;/code&gt; manifest file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-toml&#34;&gt;[setup.backends.httpme]&#xA;address = &amp;quot;http-me.glitch.me&amp;quot;&#xA;port = 443&#xA;&#xA;[local_server.backends.httpme]&#xA;override_host = &amp;quot;http-me.glitch.me&amp;quot;&#xA;url = &amp;quot;https://http-me.glitch.me&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first block &lt;code&gt;[setup.backends.httpme]&lt;/code&gt; is used only once by the CLI when you&#xA;come to deploy your service (I&amp;rsquo;ll show you that later). It tells the CLI, when&#xA;it&amp;rsquo;s creating your Compute service, to also create a backend called &lt;code&gt;httpme&lt;/code&gt; and&#xA;to make sure it has the specified address and port.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second block &lt;code&gt;[local_server.backends.httpme]&lt;/code&gt; is used by Viceroy when&#xA;running your Compute service/application locally. Whenever your code uses the&#xA;&lt;code&gt;Send&lt;/code&gt; method on a &lt;code&gt;fsthttp.Request&lt;/code&gt;, it will ensure the request is forwarded to&#xA;the specified backend, which in this case is the real service&#xA;&lt;a href=&#34;https://http-me.glitch.me&#34; target=&#34;_blank&#34;&gt;https://http-me.glitch.me&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in our application code where we have &lt;code&gt;r.Send(&amp;quot;httpme&amp;quot;)&lt;/code&gt; you can now see that&#xA;this is sending the request to a &amp;lsquo;backend&amp;rsquo; object called &lt;code&gt;httpme&lt;/code&gt; which we&amp;rsquo;ve&#xA;now defined/created indirectly via the &lt;code&gt;fastly.toml&lt;/code&gt; manifest file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, defining backends is a bit tedious, and the primary reason for this design&#xA;is security. That said, if you&amp;rsquo;re willing to forego security, then you can ask&#xA;use something called a &amp;lsquo;dynamic backend&amp;rsquo; which allows you to define backends at&#xA;runtime in your code (see &lt;a href=&#34;https://www.fastly.com/documentation/solutions/examples/register-a-dynamic-backend/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; for an example).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-caching-behaviour&#34;&gt;Fastly caching behaviour&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s look at Fastly&amp;rsquo;s caching behaviour as it&amp;rsquo;s a bit confusing. I&amp;rsquo;m going&#xA;to reference the official Fastly doc &lt;a href=&#34;https://www.fastly.com/documentation/guides/concepts/edge-state/cache/&#34; target=&#34;_blank&#34;&gt;Caching content with Fastly&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The Fastly edge cache is an enormous pool of storage across our network which&#xA;allows you to satisfy end user requests with exceptional performance and&#xA;reduce the need for requests to your origin servers. Most use cases make use&#xA;of the &lt;a href=&#34;https://www.fastly.com/documentation/guides/concepts/edge-state/cache/#readthrough-cache&#34; target=&#34;_blank&#34;&gt;readthrough cache interface&lt;/a&gt;, which works automatically with the&#xA;HTTP requests that transit your Fastly service to save responses in cache so&#xA;they can be reused. The first time a cacheable resource is requested at a&#xA;particular POP, the resource will be requested from your backend server and&#xA;stored in cache automatically. Subsequent requests for that resource can then&#xA;be satisfied from cache without having to be forwarded to your servers.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So what this means is that Fastly uses something called a &amp;lsquo;readthrough&amp;rsquo; cache by&#xA;default. The readthrough cache respects HTTP caching semantics. So if your&#xA;backend returns a response with a HTTP header such as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;Cache-Control: s-maxage=300, max-age=0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;then the readthrough cache will cache the response for 300s (i.e. it&amp;rsquo;ll use&#xA;the value assigned to &lt;code&gt;s-maxage&lt;/code&gt;). So when the next request comes into your&#xA;Compute service/application, and it reaches the &lt;code&gt;r.Send()&lt;/code&gt; line, then that will&#xA;respond immediately with the cached content and not actually make a call to the&#xA;backend.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what about the &lt;code&gt;max-age&lt;/code&gt;? Well, that&amp;rsquo;s for the browser. The user&amp;rsquo;s web&#xA;browser will only see &lt;code&gt;Cache-Control: max-age=0&lt;/code&gt; as &lt;code&gt;s-maxage&lt;/code&gt; is for proxies&#xA;and CDNs and so Fastly will strip it from the response header.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you want more information on HTTP caching then take a look at my&#xA;blog post &lt;a href=&#34;/posts/http-caching-guide/&#34;&gt;HTTP Caching Guide&lt;/a&gt; which explains all the details.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now, this is where the following lines in our Compute service/application code&#xA;are going to affect things. Let&amp;rsquo;s take a look&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So &lt;em&gt;before&lt;/em&gt; we forwarded the incoming request to the backend (using &lt;code&gt;Send&lt;/code&gt;) we&#xA;actually configured the readthrough to ignore what is being set in the backend&amp;rsquo;s&#xA;response (i.e. ignoring the &lt;code&gt;Cache-Control&lt;/code&gt; header) and to blanket cache the&#xA;response for 30 seconds. We do this using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// https://pkg.go.dev/github.com/fastly/compute-sdk-go@v1.3.1/fsthttp#CacheOptions&#xA;r.CacheOptions.TTL = 30&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason we have to do this &lt;em&gt;before&lt;/em&gt; sending the request is because of how the&#xA;readthrough cache works (i.e. it automatically handles caching the responses).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Fastly also provides a &amp;lsquo;simple&amp;rsquo; cache interface and a more advanced&#xA;&amp;lsquo;core&amp;rsquo; cache interface exposed via the Compute SDKs. You can see examples&#xA;&lt;a href=&#34;https://www.fastly.com/documentation/guides/concepts/edge-state/cache/#interfaces&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Before we send our response to the user we actually modify the cache behaviour&#xA;again, but this time for the user&amp;rsquo;s web browser by overriding the backend&amp;rsquo;s&#xA;&lt;code&gt;max-age=0&lt;/code&gt; with &lt;code&gt;max-age=60&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;resp.Header.Set(&amp;quot;Cache-Control&amp;quot;, &amp;quot;public, max-age=60&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-warning&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;⚠️ WARNING&lt;/p&gt;&lt;p&gt;There&amp;rsquo;s a caveat to the readthrough cache that you&amp;rsquo;ll want to&#xA;be careful with. If your backend sends &lt;code&gt;Cache-Control: private&lt;/code&gt;, then&#xA;understandably the readthrough cache will not cache the response because your&#xA;backend has defined that behaviour. In this case, setting &lt;code&gt;r.CacheOptions.TTL&lt;/code&gt;&#xA;will have NO EFFECT. It&amp;rsquo;s only usable for responses that Fastly considers&#xA;&lt;em&gt;cacheable&lt;/em&gt; and &lt;code&gt;private&lt;/code&gt; is not cacheable. You would need your backend to&#xA;change the &lt;code&gt;Cache-Control&lt;/code&gt; value to be something cacheable if you wanted&#xA;&lt;code&gt;r.CacheOptions.TTL&lt;/code&gt; to have any kind of effect.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;deploying-your-compute-service&#34;&gt;Deploying your Compute service&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To wrap up this post, let&amp;rsquo;s get our Compute service/application deployed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly compute publish&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above command will prompt you whenever information is required, or you can&#xA;simplify the process and add the &lt;code&gt;--non-interactive&lt;/code&gt; flag to let Fastly choose&#xA;default values for everything:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;fastly compute publish --non-interactive&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For the first time deploying you may find it takes a bit of time because Fastly&#xA;is uploading your package across its global fleet of servers. For me I&amp;rsquo;ve&#xA;noticed the first deploy takes around ~30s but after that, any further changes I&#xA;make to my application is almost immediately uploaded/replicated 🎉&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should see output similar to the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;$ fastly compute publish --non-interactive&#xA;&#xA;✓ Verifying fastly.toml&#xA;✓ Identifying package name&#xA;✓ Identifying toolchain&#xA;✓ Running [scripts.build]&#xA;✓ Creating package archive&#xA;&#xA;SUCCESS: Built package (pkg/example.tar.gz)&#xA;&#xA;✓ Verifying fastly.toml&#xA;✓ Creating service&#xA;✓ Creating domain &#39;regularly-living-cheetah.edgecompute.app&#39;&#xA;✓ Uploading package&#xA;✓ Activating service (version 1)&#xA;✓ Checking service availability (status: 200)&#xA;&#xA;Manage this service at:&#xA;    https://manage.fastly.com/configure/services/IuZqijThLa4VawBcGy7ba6&#xA;&#xA;View this service at:&#xA;    https://regularly-living-cheetah.edgecompute.app&#xA;&#xA;SUCCESS: Deployed package (service IuZqijThLa4VawBcGy7ba6, version 1)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Good luck, and I hope you enjoy programming at the edge with Fastly 🙂&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/programming-at-the-edge-with-fastly-compute/</guid>
      <link>https://www.integralist.co.uk/posts/programming-at-the-edge-with-fastly-compute/</link>
      <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
      <title>Programming at the edge with Fastly Compute</title>
    </item>
    <item>
      <description>&lt;p&gt;The following code doesn&amp;rsquo;t do what you might expect:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;    var i *impl&#xA;&#xA;    fmt.Println(&amp;quot;i == nil:&amp;quot;, i == nil)&#xA;    what(i)&#xA;}&#xA;&#xA;type impl struct{}&#xA;&#xA;func (i *impl) do() {}&#xA;&#xA;func what(i interface{ do() }) {&#xA;    fmt.Println(&amp;quot;i == nil:&amp;quot;, i == nil)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you expected the &lt;code&gt;what&lt;/code&gt; function to print &lt;code&gt;i == nil: true&lt;/code&gt;, then keep&#xA;reading&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;typed-nils&#34;&gt;Typed Nils&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The behavior observed is due to the way interfaces and nil values interact in&#xA;Go. To understand why the &lt;code&gt;what&lt;/code&gt; function is able to see the &lt;code&gt;i&lt;/code&gt; argument as&#xA;non-nil, we need to dig into the details of how Go handles interface values.&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Interface Values: In Go, an interface value is a tuple of a type and a value.&#xA;An interface value is &lt;code&gt;nil&lt;/code&gt; only if both the type and the value are &lt;code&gt;nil&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Concrete vs Interface nil: When you assign a concrete type value (which&#xA;happens to be &lt;code&gt;nil&lt;/code&gt;) to an interface, the interface itself is not &lt;code&gt;nil&lt;/code&gt;. This&#xA;is because the interface value now contains a type (the concrete type) and a&#xA;value (&lt;code&gt;nil&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;explanation&#34;&gt;Explanation&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Declaring &lt;code&gt;var i *impl&lt;/code&gt; initializes it to &lt;code&gt;nil&lt;/code&gt;.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;i&lt;/code&gt; is a pointer to &lt;code&gt;impl&lt;/code&gt; and is initialized to &lt;code&gt;nil&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Printing &lt;code&gt;i == nil&lt;/code&gt; in &lt;code&gt;main&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;because &lt;code&gt;i&lt;/code&gt; is a &lt;code&gt;nil&lt;/code&gt; pointer to &lt;code&gt;impl&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Calling &lt;code&gt;what(i)&lt;/code&gt; function:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the function &lt;code&gt;what&lt;/code&gt; takes an argument of type &lt;code&gt;interface{ do() }&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Inside &lt;code&gt;what&lt;/code&gt; function:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;i&lt;/code&gt; (which is &lt;code&gt;nil&lt;/code&gt;) is passed to &lt;code&gt;what&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;it is assigned to the parameter &lt;code&gt;i&lt;/code&gt; of type &lt;code&gt;interface{ do() }&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Interface value construction:&lt;br&gt;&#xA;The value of &lt;code&gt;i&lt;/code&gt; inside &lt;code&gt;what&lt;/code&gt; is now an interface that holds:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Type: &lt;code&gt;*impl&lt;/code&gt; (the concrete type of the value passed in)&lt;/li&gt;&#xA;&lt;li&gt;Value: &lt;code&gt;nil&lt;/code&gt; (the value of the concrete type)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Checking &lt;code&gt;i == nil&lt;/code&gt; prints &lt;code&gt;false&lt;/code&gt; because the interface &lt;code&gt;i&lt;/code&gt; is not &lt;code&gt;nil&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The type part of the interface is &lt;code&gt;*impl&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;The value part of the interface is &lt;code&gt;nil&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;what&lt;/code&gt; function sees the &lt;code&gt;i&lt;/code&gt; argument as non-nil because, in Go, an&#xA;interface holding a &lt;code&gt;nil&lt;/code&gt; pointer is not itself &lt;code&gt;nil&lt;/code&gt;. The interface contains&#xA;type information (&lt;code&gt;*impl&lt;/code&gt;) and a &lt;code&gt;nil&lt;/code&gt; value. Therefore, when the code checks if&#xA;&lt;code&gt;i&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;, it returns &lt;code&gt;false&lt;/code&gt; since the type information (&lt;code&gt;*impl&lt;/code&gt;) is&#xA;present.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-material&#34;&gt;Reference material&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://go.dev/doc/faq#nil_error&#34; target=&#34;_blank&#34;&gt;Go FAQ&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://dave.cheney.net/2017/08/09/typed-nils-in-go-2&#34; target=&#34;_blank&#34;&gt;Dave Cheney&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-typed-nil/</guid>
      <link>https://www.integralist.co.uk/posts/go-typed-nil/</link>
      <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
      <title>Go Typed Nil</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In this post I cover what CI/CD means and how you can achieve it across multiple&#xA;different environments (e.g. dev, stage, prod) using the GitHub Actions&#xA;platform. The infrastructure is managed using Terraform and the state is&#xA;coordinated using Terraform Cloud.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I detail specific issues I experienced while implementing CI/CD for a real&#xA;high-scale/high-profile public API, and the workarounds I needed to implement to&#xA;resolve them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-ci-cd&#34;&gt;What is CI/CD?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start off by answering the question:&lt;br&gt;&#xA;&lt;em&gt;What is CI/CD&lt;/em&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;CI&lt;/em&gt; is short for Continuous Integration.&lt;br&gt;&#xA;&lt;em&gt;CD&lt;/em&gt; refers to two separate concepts:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Continuous Delivery&lt;/li&gt;&#xA;&lt;li&gt;Continuous Deployment&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;People often make the mistake of thinking they are interchangeable.&lt;br&gt;&#xA;They&amp;rsquo;re not. But what these terms mean is actually not that complicated:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Continuous Integration&lt;/strong&gt;: you&amp;rsquo;re testing every change (i.e. commit)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Continuous Delivery&lt;/strong&gt;: you&amp;rsquo;re able to ship every change on demand&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Continuous Deployment&lt;/strong&gt;: you&amp;rsquo;re shipping every change automatically&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now we have a bit of an understanding of what CI/CD is,&lt;br&gt;&#xA;let&amp;rsquo;s see how I&amp;rsquo;ve been able to use each of these individual concepts.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;api-gateway&#34;&gt;API Gateway&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I needed to implement a complete CI/CD pipeline for my employer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They had an API Gateway service which required a mixture of continuous&#xA;integration, delivery and deployment across three separate &amp;lsquo;environments&amp;rsquo; (i.e.&#xA;a dev environment, a stage environment, and a production environment).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is the summary of their usage per environment:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Dev&lt;/strong&gt;: Continuous Integration/Deployment&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Stage&lt;/strong&gt;: Continuous Integration/Deployment&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Production&lt;/strong&gt;: Continuous Delivery&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s dig into each environment to understand how they use CI/CD.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dev-environment&#34;&gt;Dev Environment&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The development environment is spun-up automatically when pushing to a PR.&lt;br&gt;&#xA;It is automatically spun-down when the associated PR is merged.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;We control which files will trigger the dev environment creation.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The service name is &lt;code&gt;api-gateway-dev-&amp;lt;BRANCH&amp;gt;&lt;/code&gt;.&lt;br&gt;&#xA;The service domain is &lt;code&gt;api-gateway-dev-&amp;lt;BRANCH&amp;gt;.edgecompute.app&lt;/code&gt;.&lt;br&gt;&#xA;The &lt;code&gt;&amp;lt;BRANCH&amp;gt;&lt;/code&gt; is calculated from &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/contexts#github-context&#34; target=&#34;_blank&#34;&gt;github.head_ref&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Terraform state that manages this environment is stored in a &lt;a href=&#34;https://www.hashicorp.com/products/terraform&#34; target=&#34;_blank&#34;&gt;Terraform&#xA;Cloud&lt;/a&gt; (TFC) project under a dynamically created, and managed,&#xA;workspace called &lt;code&gt;api-gateway-dev-&amp;lt;BRANCH&amp;gt;&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The dev CI workflow has some important steps it must take in order to spin-up a&#xA;development environment that is isolated between different PR authors:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Call the &lt;a href=&#34;https://developer.hashicorp.com/terraform/cloud-docs/api-docs&#34; target=&#34;_blank&#34;&gt;TFC API&lt;/a&gt; to create a new workspace in the TFC project.&lt;/li&gt;&#xA;&lt;li&gt;Cache the result of the workspace creation to avoid API rate limits.&lt;/li&gt;&#xA;&lt;li&gt;Also create a workspace environment variable for &lt;code&gt;FASTLY_API_KEY&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The last step is required as we&amp;rsquo;re deploying the service to &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You&amp;rsquo;ll notice shortly that our stage and production flows use a&#xA;single service and workspace, where as our dev environment is a bit more&#xA;involved and requires its own dynamically created workspace and services. This&#xA;is because we have multiple developers working on multiple features at any one&#xA;time. So we use the &amp;lsquo;branch&amp;rsquo; name as the unique identifier, and by having a&#xA;different workspace per branch it means a developer can modify the Terraform&#xA;infrastructure without affecting anyone else.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;stage-environment&#34;&gt;Stage Environment&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two scenarios where the staging environment is deployed to:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Whenever a PR is merged&lt;/li&gt;&#xA;&lt;li&gt;Whenever a commit is pushed directly to the &lt;code&gt;main&lt;/code&gt; branch&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Again, we control which files will trigger the environment creation.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The service name is &lt;code&gt;api-gateway-stg&lt;/code&gt;.&lt;br&gt;&#xA;The service domain is &lt;code&gt;api-gateway-stg.edgecompute.app&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once the deployment is complete, the Compute package (i.e. the application code)&lt;br&gt;&#xA;is uploaded as an &lt;a href=&#34;https://github.com/actions/upload-artifact&#34; target=&#34;_blank&#34;&gt;artifact to GitHub&lt;/a&gt; and is deleted after 14 days.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The name of the artifact is the hash of the Compute package.&lt;br&gt;&#xA;A git tag is pushed for each stage deployment, and the hash is appended to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;During that 14 day time frame, the artifact can be &lt;em&gt;promoted&lt;/em&gt; to production.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Terraform state that manages this environment is stored in the Terraform&#xA;Cloud project under the &amp;ldquo;api-gateway-stage&amp;rdquo; workspace.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;production-environment&#34;&gt;Production Environment&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The production environment is deployed to manually (i.e. Continuous Delivery) by&#xA;triggering the relevant GitHub Actions workflow. The person triggering the&#xA;deployment will first need to identify the Compute package &amp;lsquo;hash&amp;rsquo; (which is&#xA;appended to each staging tag).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for &amp;lsquo;promoting&amp;rsquo; the staging Compute package to production,&lt;br&gt;&#xA;rather than recompiling the application code, is to ensure consistency&lt;br&gt;&#xA;between the staging and production environments.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We require the person triggering the deployment to manually locate the relevant&#xA;Compute package hash. We can&amp;rsquo;t rely on automation&#xA;(e.g &lt;code&gt;git tag --sort=-creatordate&lt;/code&gt;) because at the moment of checking the git&#xA;tags, another&#xA;person might have merged another PR and thus we would pick up that new staging&#xA;tag and deploy the wrong artifact to the production environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason that is a concern, is because a newly merged PR should have some time&lt;br&gt;&#xA;on the staging environment for any unexpected bugs to be identified. At some&lt;br&gt;&#xA;point in the future we might have complete confidence in our test suite to move&lt;br&gt;&#xA;from Continuous Delivery to Continuous Deployment, but that time isn&amp;rsquo;t now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The service name is &lt;code&gt;api-gateway-prd&lt;/code&gt;.&lt;br&gt;&#xA;The service domain is &lt;code&gt;api-gateway-prd.edgecompute.app&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Terraform state that manages this environment is stored in the Terraform&#xA;Cloud project under the &amp;ldquo;api-gateway-production&amp;rdquo; workspace.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So here is where I&amp;rsquo;m going to display the complete set of GitHub Actions&#xA;workflow configuration. We&amp;rsquo;ll review the code and I&amp;rsquo;ll make comments about&#xA;specific sections of interest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start with dev, then we&amp;rsquo;ll see stage, and then production.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dev-config&#34;&gt;Dev Config&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# We deploy to dev environment when PR is pushed to.&#xA;# We name the environment after the branch to avoid collisions.&#xA;# When PR is merged we automatically tear-down the dev environment.&#xA;name: &amp;quot;API Gateway TF Dev&amp;quot;&#xA;&#xA;# Stop any in-flight CI jobs when a new commit is pushed.&#xA;concurrency:&#xA;  group: api-gateway-dev-${{ github.ref_name }}&#xA;  cancel-in-progress: true&#xA;&#xA;on:&#xA;  workflow_dispatch:&#xA;  pull_request:&#xA;    types: [opened, edited, closed, reopened, synchronize]&#xA;    paths:&#xA;      - .github/workflows/api-gateway-*&#xA;      - cmd/gateway/**&#xA;      - internal/gateway/**&#xA;      - infrastructure/fastly/compute/api-gateway/**&#xA;&#xA;# IMPORTANT: for TF_VAR_* wrap double-quotes in single-quotes.&#xA;env:&#xA;  APP_DIRECTORY: &amp;quot;./cmd/gateway&amp;quot;&#xA;  CONFIG_DIRECTORY: &amp;quot;./infrastructure/fastly/compute/api-gateway&amp;quot;&#xA;  PACKAGE_PATH: &amp;quot;/pkg/gateway.tar.gz&amp;quot;&#xA;  TF_API_TOKEN: &amp;quot;${{ secrets.TF_API_TOKEN }}&amp;quot;&#xA;  TF_CLOUD_ORGANIZATION: &amp;quot;example&amp;quot;&#xA;  TF_VAR_backend: &#39;&amp;quot;https://api-dev.example.com&amp;quot;&#39;&#xA;  TF_VAR_env: &#39;&amp;quot;dev&amp;quot;&#39;&#xA;&#xA;jobs:&#xA;  create-workspace:&#xA;    name: &amp;quot;Create Terraform Cloud Workspace&amp;quot;&#xA;    # The following if statement says: don&#39;t run this when the PR is closed&#xA;    if: ${{ github.event.action != &#39;closed&#39; &amp;amp;&amp;amp; github.actor != &#39;dependabot[bot]&#39; }} &#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      - name: Cache/Restore Workspace ID&#xA;        id: cache-workspace-id&#xA;        uses: actions/cache@v4&#xA;        with:&#xA;          path: tfc-workspace-id&#xA;          key: ${{ runner.os }}-cache-workspace-id-${{github.head_ref}}&#xA;&#xA;      # IMPORTANT: We don&#39;t want to run the following steps if we get a cache-hit.&#xA;      # That is because a cache-hit indiciates we&#39;ve already created the workspace.&#xA;      # This means we&#39;re forced to add a `if:` check on each following step.&#xA;&#xA;      - name: Set TF_VAR_branch&#xA;        if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;        uses: ./.github/actions/tf-var-branch&#xA;&#xA;      - name: Set WORKSPACE_NAME&#xA;        if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;        uses: ./.github/actions/tfc-dev-workspace-name&#xA;&#xA;      - name: Modify Workspace JSON Payload&#xA;        if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;        run: |&#xA;          payload=./infrastructure/fastly/compute/api-gateway/tfc-api/payloads/workspace.json&#xA;          jq &#39;.data.attributes.name = &amp;quot;${{ env.WORKSPACE_NAME }}&amp;quot;&#39; \&#xA;            &amp;quot;$payload&amp;quot; &amp;gt; temp.json &amp;amp;&amp;amp; mv temp.json &amp;quot;$payload&amp;quot;&#xA;&#xA;      - name: Modify Workspace Variable JSON Payload&#xA;        if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;        run: |&#xA;          payload=./infrastructure/fastly/compute/api-gateway/tfc-api/payloads/workspace-variables.json&#xA;          jq &#39;.data.attributes.value = &amp;quot;${{ secrets.FASTLY_API_KEY }}&amp;quot;&#39; \&#xA;            &amp;quot;$payload&amp;quot; &amp;gt; temp.json &amp;amp;&amp;amp; mv temp.json &amp;quot;$payload&amp;quot;&#xA;&#xA;      # NOTE: A cache is volatile/ephemeral.&#xA;      # If the cache is invalidated/cleared, then the following step could still&#xA;      # be run. This would mean the curl request to create the workspace would fail&#xA;      # (because it could already exist). This is OK, because we check the API&#xA;      # response for errors and the last step reacts to the failure status. The&#xA;      # intention is to avoid trying to read from a response.json that doesn&#39;t contain&#xA;      # the required structure (i.e. doesn&#39;t contain a .data.id field). As well as&#xA;      # avoid trying to call the TFC API to create a workspace variable when there was&#xA;      # an error initially creating the workspace.&#xA;&#xA;      - name: Create Dev Workspace&#xA;        if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;        run: |&#xA;          curl -s \&#xA;            --header &amp;quot;Authorization: Bearer ${{ secrets.TF_API_TOKEN }}&amp;quot; \&#xA;            --header &amp;quot;Content-Type: application/vnd.api+json&amp;quot; \&#xA;            --request POST \&#xA;            --data @infra/fastly/compute/api-gateway/tfc-api/payloads/workspace.json \&#xA;            https://app.terraform.io/api/v2/organizations/example/workspaces &amp;gt; response.json&#xA;          if [[ $(jq &#39;.errors | length == 0&#39; response.json) == false ]]; then&#xA;            jq &#39;.errors&#39; response.json&#xA;            echo &amp;quot;STEP_STATUS=failed&amp;quot; &amp;gt;&amp;gt; &amp;quot;${GITHUB_ENV}&amp;quot;&#xA;          fi&#xA;&#xA;      - name: Create FASTLY_API_KEY as Workspace Variable&#xA;        if: ${{ steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39; &amp;amp;&amp;amp; env.STEP_STATUS != &#39;failed&#39; }}&#xA;        run: |&#xA;          workspace_id=$(jq -r &#39;.data.id&#39; response.json)&#xA;          curl -s \&#xA;            --header &amp;quot;Authorization: Bearer ${{ secrets.TF_API_TOKEN }}&amp;quot; \&#xA;            --header &amp;quot;Content-Type: application/vnd.api+json&amp;quot; \&#xA;            --request POST \&#xA;            --data @infra/fastly/compute/api-gateway/tfc-api/payloads/variables.json \&#xA;            &amp;quot;https://app.terraform.io/api/v2/workspaces/$workspace_id/vars&amp;quot;&#xA;          echo &amp;quot;$workspace_id&amp;quot; &amp;gt; tfc-workspace-id&#xA;&#xA;  terraform-plan:&#xA;    name: &amp;quot;Plan&amp;quot;&#xA;    runs-on: ubuntu-latest&#xA;    permissions: # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs&#xA;      contents: read&#xA;      pull-requests: write&#xA;    needs: create-workspace&#xA;    # don&#39;t run this when the PR is closed (and also only if the create-workspace was successful)&#xA;    if: ${{ github.event.action != &#39;closed&#39; &amp;amp;&amp;amp; github.actor != &#39;dependabot[bot]&#39; &amp;amp;&amp;amp; success() }} &#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      - name: Install Go and Fastly CLI&#xA;        uses: ./.github/actions/fastly-cli&#xA;&#xA;      - name: Build Compute Package&#xA;        run: fastly compute build --dir ${{ env.APP_DIRECTORY }} --metadata-show&#xA;&#xA;      - name: Calculate Compute Package Hash&#xA;        run: fastly compute hash-files --skip-build --dir ${{ env.APP_DIRECTORY }}&#xA;&#xA;      - name: Copy Compute Package to Terraform workspace&#xA;        run: cp ${{ env.APP_DIRECTORY }}${{ env.PACKAGE_PATH }} ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;      - name: Set TF_VAR_branch&#xA;        uses: ./.github/actions/tf-var-branch&#xA;&#xA;      - name: Set WORKSPACE_NAME&#xA;        uses: ./.github/actions/tfc-dev-workspace-name&#xA;&#xA;        # NOTE: This job (and all jobs that follow) requires a TFC Workspace.&#xA;        # The name of the workspace is expected to match WORKSPACE_NAME.&#xA;        # The creation of the workspace happens in the `create-workspace` job.&#xA;        #&#xA;        # But there are scenarios where the workspace might not exist!&#xA;        # This can happen when there is an error in the `create-workspace` job.&#xA;        # For example, when calling the TFC API.&#xA;        #&#xA;        # Although the API might error, we don&#39;t want to mark the job as failed.&#xA;        # This is because the API could be called and fail for multiple reasons.&#xA;        # e.g. the cached API result wasn&#39;t found and we got a 422 from the API.&#xA;        #&#xA;        # A 422 code response from the TFC API thus indicates we tried to create&#xA;        # a workspace that already exists. So in this scenario we still want the&#xA;        # remaining jobs to run (as the workspace does exist).&#xA;        #&#xA;        # Ultimately, if the error was something else and the workspace thus&#xA;        # wasn&#39;t created, then at worst we&#39;ll get an error back from TFC when&#xA;        # trying to upload the TF configuration.&#xA;&#xA;      - name: Upload Configuration&#xA;        uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.2.0&#xA;        id: plan-upload&#xA;        with:&#xA;          workspace: ${{ env.WORKSPACE_NAME }}&#xA;          directory: ${{ env.CONFIG_DIRECTORY }}&#xA;          speculative: true&#xA;&#xA;      - name: Create Plan Run&#xA;        uses: hashicorp/tfc-workflows-github/actions/create-run@v1.2.0&#xA;        id: plan-run&#xA;        with:&#xA;          workspace: ${{ env.WORKSPACE_NAME }}&#xA;          configuration_version: ${{ steps.plan-upload.outputs.configuration_version_id }}&#xA;          plan_only: true&#xA;&#xA;      - name: Get Plan Output&#xA;        uses: hashicorp/tfc-workflows-github/actions/plan-output@v1.2.0&#xA;        id: plan-output&#xA;        with:&#xA;          plan: ${{ fromJSON(steps.plan-run.outputs.payload).data.relationships.plan.data.id }}&#xA;&#xA;      - name: Update PR&#xA;        uses: actions/github-script@v7&#xA;        id: plan-comment&#xA;        with:&#xA;          github-token: ${{ secrets.GITHUB_TOKEN }}&#xA;          script: |&#xA;            // Retrieve existing bot comments for the PR&#xA;            const { data: comments } = await github.rest.issues.listComments({&#xA;              owner: context.repo.owner,&#xA;              repo: context.repo.repo,&#xA;              issue_number: context.issue.number,&#xA;            });&#xA;            const botComment = comments.find(comment =&amp;gt; {&#xA;              return comment.user.type === &#39;Bot&#39; &amp;amp;&amp;amp; comment.body.includes(&#39;TF Plan Output&#39;)&#xA;            });&#xA;            const output = `#### Terraform Cloud Plan Output&#xA;               \`\`\`&#xA;               Plan: ${{ steps.plan-output.outputs.add }} to add, &#xA;               ${{ steps.plan-output.outputs.change }} to change, \&#xA;               ${{ steps.plan-output.outputs.destroy }} to destroy.&#xA;               \`\`\`&#xA;               [Terraform Cloud Plan](${{ steps.plan-run.outputs.run_link }})&#xA;               `;&#xA;            if (botComment) {&#xA;              github.rest.issues.deleteComment({&#xA;                owner: context.repo.owner,&#xA;                repo: context.repo.repo,&#xA;                comment_id: botComment.id,&#xA;              });&#xA;            }&#xA;            github.rest.issues.createComment({&#xA;              issue_number: context.issue.number,&#xA;              owner: context.repo.owner,&#xA;              repo: context.repo.repo,&#xA;              body: output&#xA;            });&#xA;&#xA;  terraform-apply:&#xA;    name: &amp;quot;Apply&amp;quot;&#xA;    needs: terraform-plan&#xA;    runs-on: ubuntu-latest&#xA;    permissions:&#xA;      contents: read  # for Terraform Actions&#xA;      statuses: write # for Status Action (myrotvorets/set-commit-status-action)&#xA;    # don&#39;t run this when the PR is closed (and also only if the terraform-plan was successful)&#xA;    if: ${{ github.event.action != &#39;closed&#39; &amp;amp;&amp;amp; github.actor != &#39;dependabot[bot]&#39; &amp;amp;&amp;amp; success() }} &#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      - name: Install Go and Fastly CLI&#xA;        uses: ./.github/actions/fastly-cli&#xA;&#xA;      - name: Build Compute Package&#xA;        run: fastly compute build --dir ${{ env.APP_DIRECTORY }} --metadata-show&#xA;&#xA;      - name: Calculate Compute Package Hash&#xA;        run: fastly compute hash-files --skip-build --dir ${{ env.APP_DIRECTORY }}&#xA;&#xA;      - name: Copy Compute Package to Terraform workspace&#xA;        run: cp ${{ env.APP_DIRECTORY }}${{ env.PACKAGE_PATH }} ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;      - name: Set TF_VAR_branch&#xA;        uses: ./.github/actions/tf-var-branch&#xA;&#xA;      - name: Set WORKSPACE_NAME&#xA;        uses: ./.github/actions/tfc-dev-workspace-name&#xA;&#xA;      - name: Terraform Apply&#xA;        id: tf-apply&#xA;        uses: ./.github/actions/tf-apply&#xA;        with:&#xA;          workspace: ${{ env.WORKSPACE_NAME }}&#xA;&#xA;      - name: &amp;quot;Terraform Apply Run URL&amp;quot;&#xA;        uses: myrotvorets/set-commit-status-action@master&#xA;        if: success()&#xA;        with:&#xA;          token: ${{ secrets.GITHUB_TOKEN }}&#xA;          status: &amp;quot;success&amp;quot;&#xA;          description: &amp;quot;click &#39;Details&#39; to view&amp;quot;&#xA;          context: Terraform Apply Results&#xA;          targetUrl: &amp;quot;https://app.terraform.io/app/example/workspaces/\&#xA;            api-gateway/runs/${{ steps.tf-apply.outputs.run_id }}&amp;quot;&#xA;&#xA;  # Remove any dev services once the corresponding PR has been merged.&#xA;  # https://docs.github.com/en/actions/using-workflows/\&#xA;  # events-that-trigger-workflows#running-your-pull_request-workflow-when-a-pull-request-merges&#xA;  terraform-destroy:&#xA;    name: &amp;quot;Cleanup Dev Environment&amp;quot;&#xA;    runs-on: ubuntu-latest&#xA;    if: ${{ github.event.pull_request.merged == true &amp;amp;&amp;amp; github.actor != &#39;dependabot[bot]&#39; }}&#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      # NOTE: We still need to install the CLI and compile the Compute package.&#xA;      # This is because we need to do a two-step apply (see IMPORTANT below).&#xA;&#xA;      - name: Install Go and Fastly CLI&#xA;        uses: ./.github/actions/fastly-cli&#xA;&#xA;      - name: Build Compute Package&#xA;        run: fastly compute build --dir ${{ env.APP_DIRECTORY }} --metadata-show&#xA;&#xA;      - name: Calculate Compute Package Hash&#xA;        run: fastly compute hash-files --skip-build --dir ${{ env.APP_DIRECTORY }}&#xA;&#xA;      - name: Copy Compute Package to Terraform workspace&#xA;        run: cp ${{ env.APP_DIRECTORY }}${{ env.PACKAGE_PATH }} ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;      - name: Set TF_VAR_branch&#xA;        uses: ./.github/actions/tf-var-branch&#xA;&#xA;      - name: Set WORKSPACE_NAME&#xA;        uses: ./.github/actions/tfc-dev-workspace-name&#xA;&#xA;        # IMPORTANT: Deleting a service with a resource-link is a two-step apply.&#xA;        # We can&#39;t pass a -target to the Terraform GH Action as a prerequisite step.&#xA;        # So this means we&#39;ll need to clear any `resource_link` blocks from the config.&#xA;        # Then, after we&#39;ve applied the change, we&#39;ll need to run a TF destroy.&#xA;&#xA;      - name: Remove resource_link blocks from TF config&#xA;        run: |&#xA;          while IFS= read -r line; do&#xA;              if [[ &amp;quot;$line&amp;quot; =~ &amp;quot;resource_link {&amp;quot; || &amp;quot;$clear_line&amp;quot; == true ]]; then&#xA;                if [[ &amp;quot;$line&amp;quot; =~ &amp;quot;}&amp;quot; ]]; then&#xA;                  clear_line=false&#xA;                else&#xA;                  clear_line=true&#xA;                fi&#xA;                echo &amp;quot;&amp;quot;&#xA;              else&#xA;                echo &amp;quot;$line&amp;quot;&#xA;              fi&#xA;          done &amp;lt; ${{ env.CONFIG_DIRECTORY }}/main.tf &amp;gt; ./main.tf &amp;amp;&amp;amp; \&#xA;            mv ./main.tf ${{ env.CONFIG_DIRECTORY }}/main.tf&#xA;&#xA;      - name: Terraform Apply&#xA;        uses: ./.github/actions/tf-apply&#xA;        with:&#xA;          workspace: ${{ env.WORKSPACE_NAME }}&#xA;&#xA;        # NOTE: Destroy config once Resource Links have been removed.&#xA;&#xA;      - name: Terraform Apply&#xA;        if: success()&#xA;        uses: ./.github/actions/tf-apply&#xA;        with:&#xA;          workspace: ${{ env.WORKSPACE_NAME }}&#xA;          destroy: true&#xA;&#xA;        # NOTE: Once all Fastly resources are deleted, we delete the TFC workspace.&#xA;&#xA;      - name: Delete Dev Workspace&#xA;        run: |&#xA;          curl -s \&#xA;            --header &amp;quot;Authorization: Bearer ${{ secrets.TF_API_TOKEN }}&amp;quot; \&#xA;            --header &amp;quot;Content-Type: application/vnd.api+json&amp;quot; \&#xA;            --request POST \&#xA;            https://app.terraform.io/api/v2/organizations/example/workspaces/\&#xA;            ${{ env.WORKSPACE_NAME }}/actions/safe-delete &amp;gt; response.json&#xA;          if [[ $(jq &#39;.errors | length == 0&#39; response.json) == false ]]; then&#xA;            jq &#39;.errors&#39; response.json&#xA;            exit 1&#xA;          fi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, the first thing I tripped up on was&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# Stop any in-flight CI jobs when a new commit is pushed.&#xA;concurrency:&#xA;  group: api-gateway-dev-${{ github.ref_name }}&#xA;  cancel-in-progress: true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m used to naming the &lt;code&gt;group&lt;/code&gt; with &lt;code&gt;${{ github.ref_name }}&lt;/code&gt;. This has&#xA;historically always worked fine for me, until I started developing a more&#xA;complex CI/CD pipeline where there are lots of different events causing a&#xA;workflow file to be triggered &amp;hellip;and more importantly, causing a workflow file&#xA;to be STOPPED!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically, I ran into an issue where merging a PR should cause the dev&#xA;environment to be spun-down, but I had a stage workflow also running and that&#xA;caused by dev workflow to be unexpectedly cancelled, meaning I had&#xA;infrastructure resources orphaned, and it was a pain to have to go back and&#xA;manually clean them up.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to resolve that I had to make sure to prefix each &lt;code&gt;group&lt;/code&gt; with a unique name.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing of interest is&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;on:&#xA;  workflow_dispatch:&#xA;  pull_request:&#xA;    types: [opened, edited, closed, reopened, synchronize]&#xA;    paths:&#xA;      - .github/workflows/api-gateway-*&#xA;      - cmd/gateway/**&#xA;      - internal/gateway/**&#xA;      - infrastructure/fastly/compute/api-gateway/**&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It took me a while to figure out the &lt;code&gt;types&lt;/code&gt; to use. I have a very specific set&#xA;of events I want to react to and I discovered that &lt;code&gt;edited&lt;/code&gt; on a &lt;code&gt;pull_request&lt;/code&gt;&#xA;doesn&amp;rsquo;t mean &amp;ldquo;code pushed to the PR&amp;rdquo;. Nope, for that you need &lt;code&gt;synchronize&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, I wanted to avoid having workflow files triggered unnecessarily, hence I&#xA;restrict this particular workflow file to changes made to relevant API gateway&#xA;files. Now, this isn&amp;rsquo;t perfect because the application code could change in the&#xA;future to depend on other packages in the codebase (as it&amp;rsquo;s a mono-repo) and&#xA;that would mean having to update this list (which as you can imagine is likely&#xA;to get forgotten about).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing of interest is&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# IMPORTANT: for TF_VAR_* wrap double-quotes in single-quotes.&#xA;env:&#xA;  APP_DIRECTORY: &amp;quot;./cmd/gateway&amp;quot;&#xA;  CONFIG_DIRECTORY: &amp;quot;./infrastructure/fastly/compute/api-gateway&amp;quot;&#xA;  PACKAGE_PATH: &amp;quot;/pkg/gateway.tar.gz&amp;quot;&#xA;  TF_API_TOKEN: &amp;quot;${{ secrets.TF_API_TOKEN }}&amp;quot;&#xA;  TF_CLOUD_ORGANIZATION: &amp;quot;example&amp;quot;&#xA;  TF_VAR_backend: &#39;&amp;quot;https://api-dev.example.com&amp;quot;&#39;&#xA;  TF_VAR_env: &#39;&amp;quot;dev&amp;quot;&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When passing a value to Terraform via an environment variable, you need the&#xA;value itself to be a string, but doing &lt;code&gt;export FOO=bar&lt;/code&gt; doesn&amp;rsquo;t assign &lt;code&gt;&amp;quot;bar&amp;quot;&lt;/code&gt;&#xA;to the variable, it only assigns &lt;code&gt;bar&lt;/code&gt; without the quotes and that causes&#xA;Terraform to treat the value like an undefined variable. So it&amp;rsquo;s very important&#xA;to wrap the string in single quotes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing of interest is&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# don&#39;t run this when the PR is closed&#xA;if: ${{ github.event.action != &#39;closed&#39; &amp;amp;&amp;amp; github.actor != &#39;dependabot[bot]&#39; }} &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Specifically, the bit I want to call out is the check for &lt;code&gt;dependabot[bot]&lt;/code&gt;.&#xA;This is because when this automated-bot opens a PR on your repo, it won&amp;rsquo;t have&#xA;access to your secrets and so it won&amp;rsquo;t be able to make TFC API calls (and do&#xA;other things) so you might as well skip the CI/CD pipeline workflow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next difficulty I ran into was figuring out how best to avoid API rate&#xA;limits from the Terraform Cloud API. This particular set of workflow files would&#xA;be run many multiple times a day, and using the TFC API each time would quickly&#xA;cause us to hit a rate-limit threshold.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid that situation I needed to figure out clever caching patterns. But&#xA;then, I needed to also account for the fact that a cache is volatile/ephemeral&#xA;and can cause unexpected error scenarios.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you take a look at the &lt;code&gt;create-workspace&lt;/code&gt; job, you&amp;rsquo;ll see that once I&#xA;successfully create a new workspace, I&amp;rsquo;ll then call the API to create an&#xA;environment variable that contains a required secret value (for interacting with&#xA;the Fastly API) and when that is successful I create a file called&#xA;&lt;code&gt;tfc-workspace-id&lt;/code&gt; and it&amp;rsquo;s that file that I cache and restore on each job run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When the workflow calls the &lt;code&gt;terraform-plan&lt;/code&gt; job you&amp;rsquo;ll see I&amp;rsquo;ve added a comment&#xA;about handling error scenarios. Originally, I would depend on the&#xA;&lt;code&gt;create-workspace&lt;/code&gt; job and only run &lt;code&gt;terraform-plan&lt;/code&gt; if the other job had&#xA;completed successfully. But that didn&amp;rsquo;t always work and ties back to my comment&#xA;about a cache being volatile/ephemeral.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To explain: the &lt;code&gt;terraform-plan&lt;/code&gt; job (and all jobs that follow it) requires a&#xA;TFC Workspace. The name of the workspace is expected to match &lt;code&gt;WORKSPACE_NAME&lt;/code&gt;.&#xA;The creation of the workspace happens in the &lt;code&gt;create-workspace&lt;/code&gt; job.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Part of the &lt;code&gt;create-workspace&lt;/code&gt; is making API requests, and to make that easier I&#xA;pass a JSON file in to be used as the data input rather than manually&#xA;configuring it in a single &lt;code&gt;curl&lt;/code&gt; call. But first I have to modify the JSON data&#xA;to include the values required (as I don&amp;rsquo;t want them hardcoded into the JSON):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;  - name: Modify Workspace JSON Payload&#xA;    if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;    run: |&#xA;      payload=./infrastructure/fastly/compute/api-gateway/tfc-api/payloads/workspace.json&#xA;      jq &#39;.data.attributes.name = &amp;quot;${{ env.WORKSPACE_NAME }}&amp;quot;&#39; &amp;quot;$payload&amp;quot; \&#xA;        &amp;gt; temp.json &amp;amp;&amp;amp; mv temp.json &amp;quot;$payload&amp;quot;&#xA;&#xA;  - name: Modify Workspace Variable JSON Payload&#xA;    if: steps.cache-workspace-id.outputs.cache-hit != &#39;true&#39;&#xA;    run: |&#xA;      payload=./infrastructure/fastly/compute/api-gateway/tfc-api/payloads/workspace-variables.json&#xA;      jq &#39;.data.attributes.value = &amp;quot;${{ secrets.FASTLY_API_KEY }}&amp;quot;&#39; \&#xA;        &amp;quot;$payload&amp;quot; &amp;gt; temp.json &amp;amp;&amp;amp; mv temp.json &amp;quot;$payload&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the payload JSON for both API calls:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&#xA;  &amp;quot;data&amp;quot;: {&#xA;    &amp;quot;type&amp;quot;: &amp;quot;workspaces&amp;quot;,&#xA;    &amp;quot;attributes&amp;quot;: {&#xA;      &amp;quot;name&amp;quot;: &amp;quot;api-gateway-dev-&amp;quot;&#xA;    },&#xA;    &amp;quot;relationships&amp;quot;: {&#xA;      &amp;quot;project&amp;quot;: {&#xA;        &amp;quot;data&amp;quot;: {&#xA;          &amp;quot;type&amp;quot;: &amp;quot;projects&amp;quot;,&#xA;          &amp;quot;id&amp;quot;: &amp;quot;prj-&amp;lt;REDACTED&amp;gt;&amp;quot;&#xA;        }&#xA;      }&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&#xA;  &amp;quot;data&amp;quot;: {&#xA;    &amp;quot;type&amp;quot;: &amp;quot;vars&amp;quot;,&#xA;    &amp;quot;attributes&amp;quot;: {&#xA;      &amp;quot;key&amp;quot;: &amp;quot;FASTLY_API_KEY&amp;quot;,&#xA;      &amp;quot;value&amp;quot;: &amp;quot;&amp;quot;,&#xA;      &amp;quot;description&amp;quot;: &amp;quot;API key used by the Fastly Terraform Provider&amp;quot;,&#xA;      &amp;quot;category&amp;quot;: &amp;quot;env&amp;quot;,&#xA;      &amp;quot;sensitive&amp;quot;: true&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But there are scenarios where the workspace might not exist! This can happen&#xA;when there is an error in the &lt;code&gt;create-workspace&lt;/code&gt; job. For example, when calling&#xA;the TFC API. Although the API might error, we don&amp;rsquo;t want to mark the job as not&#xA;being successful. This is because the API could be called and fail for multiple&#xA;reasons. e.g. the cached API result wasn&amp;rsquo;t found and we got a 422 from the API.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A 422 code response from the TFC API thus indicates we tried to create a&#xA;workspace that already exists. So in this scenario we still want the remaining&#xA;jobs to run (as the workspace does exist).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately, if the error was something else and the workspace thus wasn&amp;rsquo;t&#xA;created, then at worst we&amp;rsquo;ll get an error back from TFC when trying to upload&#xA;the TF configuration to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The last issue worth noting is related to tearing-down the infrastructure when&#xA;the PR is merged. There was an issue with the Fastly Terraform provider (or more&#xA;specifically a Fastly API issue) where the removal of a Fastly &amp;lsquo;Config Store&amp;rsquo;&#xA;(which was needed by the application code) has to be done as a two-part&#xA;terraform apply.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;i.e. you have to remove the &lt;code&gt;resource_link&lt;/code&gt; block from the&#xA;&lt;code&gt;fastly_service_compute&lt;/code&gt; resource and run &lt;code&gt;terraform apply&lt;/code&gt;, and then you can&#xA;trigger a &lt;code&gt;terraform apply -destroy&lt;/code&gt; via the HashiCorp GitHub Action using the&#xA;&lt;code&gt;is_destroy&lt;/code&gt; field.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;stage-config&#34;&gt;Stage Config&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# We deploy to staging environment when PR is merged or we push to `main`.&#xA;name: &amp;quot;API Gateway TF Stage&amp;quot;&#xA;&#xA;# Stop any in-flight CI jobs when a new commit is pushed.&#xA;concurrency:&#xA;  group: api-gateway-stg-${{ github.ref_name }}&#xA;  cancel-in-progress: true&#xA;&#xA;on:&#xA;  workflow_dispatch:&#xA;  push:&#xA;    branches:&#xA;      - main&#xA;    paths:&#xA;      - .github/workflows/api-gateway-*&#xA;      - cmd/gateway/**&#xA;      - internal/gateway/**&#xA;      - infrastructure/fastly/compute/api-gateway/**&#xA;&#xA;# IMPORTANT: for TF_VAR_* wrap double-quotes in single-quotes.&#xA;env:&#xA;  APP_DIRECTORY: &amp;quot;./cmd/gateway&amp;quot;&#xA;  CONFIG_DIRECTORY: &amp;quot;./infrastructure/fastly/compute/api-gateway&amp;quot;&#xA;  PACKAGE_PATH: &amp;quot;/pkg/gateway.tar.gz&amp;quot;&#xA;  TF_API_TOKEN: &amp;quot;${{ secrets.TF_API_TOKEN }}&amp;quot;&#xA;  TF_CLOUD_ORGANIZATION: &amp;quot;example&amp;quot;&#xA;  TF_VAR_backend: &#39;&amp;quot;https://api-stage.example.com&amp;quot;&#39;&#xA;  TF_VAR_env: &#39;&amp;quot;stg&amp;quot;&#39;&#xA;  TF_WORKSPACE: &amp;quot;api-gateway-stage&amp;quot;&#xA;&#xA;jobs:&#xA;  terraform-apply:&#xA;    name: &amp;quot;Apply&amp;quot;&#xA;    runs-on: ubuntu-latest&#xA;    permissions:&#xA;      contents: write&#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      - name: Install Go and Fastly CLI&#xA;        uses: ./.github/actions/fastly-cli&#xA;&#xA;      - name: Build Compute Package&#xA;        run: fastly compute build --dir ${{ env.APP_DIRECTORY }}&#xA;&#xA;      - name: Calculate Compute Package Hash&#xA;        id: cph&#xA;        run: |&#xA;          echo &amp;quot;compute_package_hash=\&#xA;          $(fastly compute hash-files --skip-build --dir ${{ env.APP_DIRECTORY }} --quiet)&amp;quot;\ &#xA;          &amp;gt;&amp;gt; $GITHUB_OUTPUT&#xA;&#xA;      - name: Copy Compute Package to Terraform workspace&#xA;        run: cp ${{ env.APP_DIRECTORY }}${{ env.PACKAGE_PATH }} ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;      - name: Terraform Apply&#xA;        uses: ./.github/actions/tf-apply&#xA;        with:&#xA;          workspace: ${{ env.TF_WORKSPACE }}&#xA;&#xA;      - name: Upload file as artifact&#xA;        uses: actions/upload-artifact@v4&#xA;        with:&#xA;          name: ${{ steps.compute-package-hash.outputs.compute_package_hash }}&#xA;          path: ${{ env.APP_DIRECTORY }}${{ env.PACKAGE_PATH }}&#xA;          retention-days: 14&#xA;          overwrite: true&#xA;&#xA;      - name: Create Git Tag&#xA;        run: |&#xA;          echo &amp;quot;GIT_STAGE_TAG=stg/$(date +&#39;%Y-%m-%d/%H-%M-%SZ&#39;)/\&#xA;          $(echo ${{ github.triggering_actor }} | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39; | \&#xA;          tr -d &#39; &#39;)/${{ steps.cph.outputs.compute_package_hash }}&amp;quot; &amp;gt;&amp;gt; &amp;quot;${GITHUB_ENV}&amp;quot;&#xA;&#xA;      - name: Check Git Tag&#xA;        run: echo &amp;quot;$GIT_STAGE_TAG&amp;quot;&#xA;&#xA;      - name: Apply Git Tag&#xA;        uses: actions/github-script@v7&#xA;        with:&#xA;          script: |&#xA;            github.rest.git.createRef({&#xA;              owner: context.repo.owner,&#xA;              repo: context.repo.repo,&#xA;              ref: &#39;refs/tags/${{ env.GIT_STAGE_TAG }}&#39;,&#xA;              sha: context.sha&#xA;            })&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The stage config isn&amp;rsquo;t as complex as the dev workflow, but there are some things&#xA;of interest to point out, such as uploading our Compute package (which is our&#xA;application code) to GitHub, which is for the purposes of later promoting that&#xA;same package to production.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We then use the hash of the Compute package as part of a git tag for staging&#xA;deploys. Again, this hash is required for the promoting of the staging artifact&#xA;to the production environment.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;production-config&#34;&gt;Production Config&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# We deploy to production environment when workflow is triggered manually.&#xA;# Person triggering workflow must provide hash of Compute package to deploy.&#xA;name: &amp;quot;API Gateway TF Prod&amp;quot;&#xA;&#xA;# Stop any in-flight CI jobs when a new commit is pushed.&#xA;concurrency:&#xA;  group: api-gateway-prd-${{ github.ref_name }}&#xA;  cancel-in-progress: true&#xA;&#xA;on:&#xA;  workflow_dispatch:&#xA;    inputs:&#xA;      compute_package_hash:&#xA;        type: string&#xA;        required: true&#xA;        description: hash of compute package (see `git tag`)&#xA;&#xA;# IMPORTANT: for TF_VAR_* wrap double-quotes in single-quotes.&#xA;env:&#xA;  APP_DIRECTORY: &amp;quot;./cmd/gateway&amp;quot;&#xA;  CONFIG_DIRECTORY: &amp;quot;./infrastructure/fastly/compute/api-gateway&amp;quot;&#xA;  GH_TOKEN: ${{ github.token }} # Required to use the `gh` CLI&#xA;  PACKAGE_PATH: &amp;quot;/pkg/gateway.tar.gz&amp;quot;&#xA;  TF_API_TOKEN: &amp;quot;${{ secrets.TF_API_TOKEN }}&amp;quot;&#xA;  TF_CLOUD_ORGANIZATION: &amp;quot;example&amp;quot;&#xA;  TF_VAR_backend: &#39;&amp;quot;https://api.example.com&amp;quot;&#39;&#xA;  TF_VAR_env: &#39;&amp;quot;prd&amp;quot;&#39;&#xA;  TF_WORKSPACE: &amp;quot;api-gateway-production&amp;quot;&#xA;&#xA;jobs:&#xA;  terraform-apply:&#xA;    name: &amp;quot;Apply&amp;quot;&#xA;    runs-on: ubuntu-latest&#xA;    permissions:&#xA;      actions: read&#xA;      contents: write&#xA;    steps:&#xA;      - name: Checkout&#xA;        uses: actions/checkout@v4&#xA;&#xA;      - name: Debug Information&#xA;        uses: ./.github/actions/debug&#xA;&#xA;      - name: Set up Go&#xA;        uses: actions/setup-go@v5&#xA;        with:&#xA;          go-version-file: go.mod&#xA;&#xA;      - name: Download Compute Package to Terraform workspace&#xA;        run: |&#xA;          gh run download -n ${{ inputs.compute_package_hash }}&#xA;          mv gateway.tar.gz ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;      - name: Terraform Apply&#xA;        uses: ./.github/actions/tf-apply&#xA;        with:&#xA;          workspace: ${{ env.TF_WORKSPACE }}&#xA;&#xA;      - name: Create Git Tag&#xA;        run: |&#xA;          echo &amp;quot;GIT_PROD_TAG=prd/$(date +&#39;%Y-%m-%d/%H-%M-%SZ&#39;)/\&#xA;          $(echo ${{ github.triggering_actor }} | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39; |\&#xA;          tr -d &#39; &#39;)/${{ inputs.compute_package_hash }}&amp;quot; &amp;gt;&amp;gt; &amp;quot;${GITHUB_ENV}&amp;quot;&#xA;&#xA;      - name: Check Git Tag&#xA;        run: echo &amp;quot;$GIT_PROD_TAG&amp;quot;&#xA;&#xA;      - name: Apply Git Tag&#xA;        uses: actions/github-script@v7&#xA;        with:&#xA;          script: |&#xA;            github.rest.git.createRef({&#xA;              owner: context.repo.owner,&#xA;              repo: context.repo.repo,&#xA;              ref: &#39;refs/tags/${{ env.GIT_PROD_TAG }}&#39;,&#xA;              sha: context.sha&#xA;            })&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, this workflow isn&amp;rsquo;t as complex as the dev one, so the only interesting&#xA;part here is that we&amp;rsquo;re downloading the artifact from GitHub and then running a&#xA;Terraform apply to upload the Compute package to our production environment.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-actions&#34;&gt;Custom Actions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The only other files probably worth showing you are the&#xA;&lt;code&gt;.github/actions/tf-var-branch&lt;/code&gt;, &lt;code&gt;.github/actions/tfc-dev-workspace-name&lt;/code&gt; and&#xA;&lt;code&gt;.github/actions/tf-apply&lt;/code&gt; steps which I moved into separate action files to&#xA;make them easier to reuse.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is &lt;code&gt;tf-var-branch&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: &amp;quot;Terraform Variable Branch Calculation&amp;quot;&#xA;description: &amp;quot;Generates a value for TF_VAR_branch&amp;quot;&#xA;runs:&#xA;  using: composite&#xA;  steps:&#xA;    - name: Set TF_VAR_branch&#xA;      shell: bash&#xA;      run: |&#xA;        echo &amp;quot;TF_VAR_branch=\&amp;quot;-$(echo ${{ github.head_ref }} |\ &#xA;        tr &#39;[:upper:]&#39; &#39;[:lower:]&#39; | tr &#39;/&#39; &#39;-&#39; | tr &#39;.&#39; &#39;-&#39; |\&#xA;        tr &#39;_&#39; &#39;-&#39;)\&amp;quot;&amp;quot; &amp;gt;&amp;gt; &amp;quot;${GITHUB_ENV}&amp;quot;&#xA;        # NOTE: We only set the branch variable for dev (stg/prd will use an empty string).&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I had to update this action twice. The first was to replace dot&#xA;characters with a hyphen as TFC complained. The second was to replace&#xA;underscores with a hyphen as Fastly complained (i.e. an underscore is not a&#xA;valid character in a domain).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is &lt;code&gt;tfc-dev-workspace-name&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: &amp;quot;Terraform Cloud Dev Workspace Name&amp;quot;&#xA;description: &amp;quot;Generates a workspace name for the PR dev environment&amp;quot;&#xA;runs:&#xA;  using: composite&#xA;  steps:&#xA;    - name: Set WORKSPACE_NAME&#xA;      shell: bash&#xA;      run: |&#xA;        # e.g. `&amp;quot;-example&amp;quot;` (set in ../tf-var-branch/action.yml)&#xA;        branch_quoted=&#39;${{ env.TF_VAR_branch }}&#39; &#xA;        # strip the leading quote (e.g. turn `&amp;quot;-example&amp;quot;` to `-example&amp;quot;`)&#xA;        branch_strip_leading_quote=&amp;quot;${branch_quoted#\&amp;quot;}&amp;quot; &#xA;        # strip the trailing quote (e.g. turn `-example&amp;quot;` to `-example`)&#xA;        branch=&amp;quot;${branch_strip_leading_quote%\&amp;quot;}&amp;quot; &#xA;        echo &amp;quot;WORKSPACE_NAME=api-gateway-dev${branch}&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is &lt;code&gt;tf-apply&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# yamllint disable rule:line-length&#xA;&#xA;name: &amp;quot;Terraform Apply&amp;quot;&#xA;description: &amp;quot;Uploads TF config, creates a run and applies it&amp;quot;&#xA;inputs:&#xA;  workspace:&#xA;    description: &amp;quot;The TFC Workspace&amp;quot;&#xA;    required: true&#xA;  destroy:&#xA;    description: &amp;quot;When true, this uses terraform to DESTROY the managed infrastructure&amp;quot;&#xA;    default: &amp;quot;false&amp;quot;&#xA;outputs:&#xA;  run_id:&#xA;    description: &amp;quot;The ID of the created run&amp;quot;&#xA;    value: ${{ steps.apply.outputs.run_id }}&#xA;runs:&#xA;  using: composite&#xA;  steps:&#xA;    - name: Upload Configuration&#xA;      uses: hashicorp/tfc-workflows-github/actions/upload-configuration@v1.2.0&#xA;      id: apply-upload&#xA;      with:&#xA;        workspace: ${{ inputs.workspace }}&#xA;        directory: ${{ env.CONFIG_DIRECTORY }}&#xA;&#xA;    - name: Create Apply Run&#xA;      uses: hashicorp/tfc-workflows-github/actions/create-run@v1.2.0&#xA;      id: apply-run&#xA;      with:&#xA;        workspace: ${{ inputs.workspace }}&#xA;        configuration_version: ${{ steps.apply-upload.outputs.configuration_version_id }}&#xA;        # IMPORTANT: This will DESTROY the dev infrastructure.&#xA;        is_destroy: ${{ inputs.destroy == true || inputs.destroy == &#39;true&#39; }}  &#xA;&#xA;    - name: Apply&#xA;      uses: hashicorp/tfc-workflows-github/actions/apply-run@v1.2.0&#xA;      if: fromJSON(steps.apply-run.outputs.payload).data.attributes.actions.IsConfirmable&#xA;      id: apply&#xA;      with:&#xA;        run: ${{ steps.apply-run.outputs.run_id }}&#xA;        comment: &amp;quot;Apply Run from GitHub Actions CI ${{ github.sha }}&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve not covered every single line of code in the GitHub configuration. I&amp;rsquo;ve&#xA;also not included the Terraform config files because they are specific to my use&#xA;case and so would be considered &amp;lsquo;noise&amp;rsquo; as far as understanding the fundamental&#xA;CI/CD flow we&amp;rsquo;re trying to learn about here.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But hopefully the explanation of each environment workflow, and then being able&#xA;to compare that to the actual implementation files for GitHub Actions is enough&#xA;to help you see how you might be able to implement your own CI/CD workflow&#xA;across multiple environments.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Good luck out there!&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/ci-cd-with-terraform-cloud-and-github-actions/</guid>
      <link>https://www.integralist.co.uk/posts/ci-cd-with-terraform-cloud-and-github-actions/</link>
      <pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate>
      <title>Continuous Integration and Deployment to multiple environments with Terraform Cloud and GitHub Actions</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In the rapidly evolving landscape of software development, creating robust and user-friendly APIs has become essential. One tool that has gained immense popularity for designing, documenting, and testing APIs is OpenAPI.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this comprehensive guide, we&amp;rsquo;ll explore why OpenAPI is so important, how to write an OpenAPI document, and the key sections you need to know. Whether you&amp;rsquo;re a seasoned developer or just getting started, mastering OpenAPI can greatly enhance your API development process.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-openapi-matters&#34;&gt;Why OpenAPI Matters&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OpenAPI, formerly known as Swagger, is an open-standard format for describing APIs. It serves as both a machine-readable and human-friendly documentation that enables developers to understand, visualize, and interact with APIs effortlessly. By defining your API using OpenAPI, you unlock a host of benefits:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Clear Documentation&lt;/strong&gt;: OpenAPI provides a clear and structured way to document your API, making it easy for both developers and non-developers to understand how to use it.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: With a standardized format, your API documentation and implementation remain consistent, reducing confusion and enhancing collaboration among teams.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Code Generation&lt;/strong&gt;: OpenAPI enables automatic code generation for client libraries and server stubs in various programming languages, saving time and effort during development.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Testing and Validation&lt;/strong&gt;: The OpenAPI specification can be used to validate requests and responses, ensuring that your API adheres to the defined contract.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Interactive Documentation&lt;/strong&gt;: Tools like &lt;a href=&#34;https://swagger.io/tools/swagger-ui/&#34; target=&#34;_blank&#34;&gt;Swagger UI&lt;/a&gt; and &lt;a href=&#34;https://github.com/Redocly/redoc&#34; target=&#34;_blank&#34;&gt;ReDoc&lt;/a&gt; allow you to create interactive documentation that lets users explore and test your API in real-time.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;summary-for-those-short-on-time&#34;&gt;Summary for those short on time&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OpenAPI is straightforward to write once you understand the high-level structure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an OpenAPI document to get you going as a basic example&lt;br&gt;&#xA;but read the full post to understand the details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also check out the related blog post on &lt;a href=&#34;https://dev.to/fastly&#34; target=&#34;_blank&#34;&gt;Fastly&amp;rsquo;s dev.to blog&lt;/a&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://dev.to/fastly/better-fastly-api-clients-with-openapi-generator-3lno&#34; target=&#34;_blank&#34;&gt;Better Fastly API clients with OpenAPI Generator&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;openapi: 3.0.3&#xA;&#xA;info:&#xA;  title: Your API&#xA;  version: 1.0.0&#xA;&#xA;servers:&#xA;  - url: https://api.example.com&#xA;&#xA;paths:&#xA;  /teams/{team_id}/members:&#xA;    parameters:&#xA;      - $ref: &amp;quot;#/components/parameters/team_id&amp;quot;&#xA;    get:&#xA;      summary: List team members&#xA;      description: List all members for the specified team.&#xA;      operationId: list-members&#xA;      responses:&#xA;        &amp;quot;200&amp;quot;:&#xA;          description: OK&#xA;          content:&#xA;            application/json:&#xA;              schema:&#xA;                $ref: &amp;quot;#/components/schemas/list_members_response&amp;quot;&#xA;              examples:&#xA;                body:&#xA;                  $ref: &amp;quot;#/components/examples/list_members_response&amp;quot;&#xA;&#xA;components:&#xA;  parameters:&#xA;    team_id:&#xA;      name: team_id&#xA;      in: path&#xA;      required: true&#xA;      style: simple&#xA;      schema:&#xA;        $ref: &amp;quot;#/components/schemas/team_id&amp;quot;&#xA;&#xA;  schemas:&#xA;    team_id:&#xA;      type: string&#xA;      description: Alphanumeric string identifying a team.&#xA;      example: AB1C2defGhijKLMNop3qR&#xA;&#xA;    list_members_response:&#xA;      type: array&#xA;      description: List of members within the specified team.&#xA;      items:&#xA;        type: string&#xA;&#xA;  examples:&#xA;    list_members_response:&#xA;      value:&#xA;        - &amp;quot;Andrew&amp;quot;&#xA;        - &amp;quot;Bob&amp;quot;&#xA;        - &amp;quot;Christine&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above example OpenAPI document describes an API. Specifically it describes:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The OpenAPI version supported (i.e. &lt;code&gt;openapi:&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Some API Metadata (i.e. &lt;code&gt;info:&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;The API address (i.e. &lt;code&gt;server:&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Supported API endpoints (i.e. &lt;code&gt;paths:&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Different &amp;lsquo;components&amp;rsquo; referenced by the &lt;code&gt;paths:&lt;/code&gt; configuration (i.e.&#xA;&lt;code&gt;components:&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In practice the last section &lt;code&gt;components:&lt;/code&gt; is where most of the &amp;lsquo;meat&amp;rsquo; of the&#xA;API configuration happens. You&amp;rsquo;ll see it contains different sections like&#xA;&lt;code&gt;parameters&lt;/code&gt;, &lt;code&gt;schemas&lt;/code&gt; and &lt;code&gt;examples&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;paths:&lt;/code&gt; section typically doesn&amp;rsquo;t define behaviours &lt;em&gt;inline&lt;/em&gt; but instead&#xA;will reference objects defined inside of &lt;code&gt;components:&lt;/code&gt; whenever they need to&#xA;describe some behaviour of the endpoint.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Any time you see &lt;code&gt;$ref&lt;/code&gt; that means we&amp;rsquo;re about to reference an object defined&#xA;elsewhere (might be in the same file, under &lt;code&gt;components:&lt;/code&gt; or it could be from a&#xA;separate file).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in the above example we can see the &lt;code&gt;paths:&lt;/code&gt; config references a few&#xA;different components:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;#/components/parameters/team_id&lt;/code&gt;: this describes the API path&amp;rsquo;s &lt;code&gt;team_id&lt;/code&gt; input parameter.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This parameter object also references a component (&lt;code&gt;#/components/schemas/team_id&lt;/code&gt;) for describing the&#xA;team_id.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;#/components/schemas/list_members_response&lt;/code&gt;: this describes the schema for&#xA;how the response body should look for this API endpoint.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;#/components/examples/list_members_response&lt;/code&gt;: this demonstrates an example of&#xA;what the schema looks like in practice.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This is the basic &lt;em&gt;structure&lt;/em&gt; of an OpenAPI document. Yes, they can become more&#xA;complex as the API grows, but at its foundation you will always find this&#xA;familiar structure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, we&amp;rsquo;ve got the quick &amp;ldquo;summary&amp;rdquo; out of the way, let&amp;rsquo;s dig a little deeper&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;getting-started-with-openapi&#34;&gt;Getting Started with OpenAPI&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before diving into the intricacies of writing an OpenAPI document, let&amp;rsquo;s set up the basics.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If at any point throughout this post you are in doubt or you require some additional clarity, then please refer to the &lt;a href=&#34;https://spec.openapis.org/oas/latest.html&#34; target=&#34;_blank&#34;&gt;specification document&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve used version &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;3.0.3&lt;/code&gt;&lt;/a&gt; for my examples.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;basic-structure&#34;&gt;Basic Structure&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An OpenAPI document is written in YAML or JSON format (I&amp;rsquo;ve used YAML for my examples).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It consists of various sections that collectively describe your API.&lt;br&gt;&#xA;At a high level, here&amp;rsquo;s what the structure looks like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;openapi: 3.0.3&#xA;info:&#xA;  title: Your API&#xA;  version: 1.0.0&#xA;paths: {}&#xA;components: {}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above example is not exhaustive as it only describes three &amp;lsquo;objects&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;info&lt;/code&gt;: &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#info-object&#34; target=&#34;_blank&#34;&gt;Info Object&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;paths&lt;/code&gt;: &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#paths-object&#34; target=&#34;_blank&#34;&gt;Paths Object&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;components&lt;/code&gt;: &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#components-object&#34; target=&#34;_blank&#34;&gt;Components Object&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Refer to the &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#openapi-object&#34; target=&#34;_blank&#34;&gt;OpenAPI Object&lt;/a&gt; for a complete list of top-level (i.e. root object) fields.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;defining-endpoints&#34;&gt;Defining Endpoints&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now, let&amp;rsquo;s break down the process of defining endpoints in your OpenAPI document.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;paths-and-methods&#34;&gt;Paths and Methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Endpoints are defined using the &lt;code&gt;paths&lt;/code&gt; section. Each endpoint is associated with an HTTP method (e.g., GET, POST) and a URL path. Here&amp;rsquo;s an example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;paths:&#xA;  /users:&#xA;    get:&#xA;      summary: Get a list of users&#xA;      responses:&#xA;        &#39;200&#39;:&#xA;          description: Successful response&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#path-item-object&#34; target=&#34;_blank&#34;&gt;Path Item Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;parameters&#34;&gt;Parameters&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can add parameters to your endpoints using the &lt;code&gt;parameters&lt;/code&gt; section. Parameters can be path parameters, query parameters, headers, and more. Here&amp;rsquo;s an example of a path parameter:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;paths:&#xA;  /users/{userId}:&#xA;    parameters:&#xA;      - name: userId&#xA;        in: path&#xA;        required: true&#xA;        schema:&#xA;          type: integer&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Possible values for the &lt;code&gt;in&lt;/code&gt; field are: &amp;ldquo;query&amp;rdquo;, &amp;ldquo;header&amp;rdquo;, &amp;ldquo;path&amp;rdquo; or &amp;ldquo;cookie&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#parameter-object&#34; target=&#34;_blank&#34;&gt;Parameter Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;structuring-data&#34;&gt;Structuring Data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Defining request and response bodies, along with data types, is crucial for a well-documented API.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;request-and-response-bodies&#34;&gt;Request and Response Bodies&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can specify request and response bodies using the &lt;code&gt;requestBody&lt;/code&gt; and &lt;code&gt;responses&lt;/code&gt; sections. Here&amp;rsquo;s how to define a request body:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;paths:&#xA;  /users:&#xA;    post:&#xA;      requestBody:&#xA;        required: true&#xA;        content:&#xA;          application/json:&#xA;            schema:&#xA;              $ref: &#39;#/components/schemas/User&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The use of &lt;code&gt;$ref&lt;/code&gt; allows us to avoid having an inline schema for one that is defined separately from the path object. This is useful in scenarios where the referenced schema might need to be reused across different paths. We&amp;rsquo;ll take a look at the &lt;code&gt;components/schemas&lt;/code&gt; section &lt;a href=&#34;#data-types&#34;&gt;next&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#operationObject&#34; target=&#34;_blank&#34;&gt;Operation Object&lt;/a&gt; and &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#requestBodyObject&#34; target=&#34;_blank&#34;&gt;Request Body Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;data-types&#34;&gt;Data Types&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Data types are defined under the &lt;code&gt;components/schemas&lt;/code&gt; section.&lt;br&gt;&#xA;Here&amp;rsquo;s an example of defining a &lt;code&gt;User&lt;/code&gt; schema:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;components:&#xA;  schemas:&#xA;    User:&#xA;      type: object&#xA;      properties:&#xA;        id:&#xA;          type: integer&#xA;        username:&#xA;          type: string&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;components&lt;/code&gt; section not only supports defining &lt;code&gt;schemas&lt;/code&gt; separate from where they should be referenced but also &lt;code&gt;responses&lt;/code&gt;, &lt;code&gt;parameters&lt;/code&gt;, &lt;code&gt;examples&lt;/code&gt; and more. We&amp;rsquo;ll take a look at some of these fields in more detail later.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#components-object&#34; target=&#34;_blank&#34;&gt;Components Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;adding-metadata&#34;&gt;Adding Metadata&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Enhance your API documentation by adding metadata and grouping related endpoints.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;api-information&#34;&gt;API Information&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;info&lt;/code&gt; section provides high-level information about your API, such as title, version, and description:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;info:&#xA;  title: Your API&#xA;  version: 1.0.0&#xA;  description: This is a sample API documentation.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#info-object&#34; target=&#34;_blank&#34;&gt;Info Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;tags-and-grouping&#34;&gt;Tags and Grouping&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can group related endpoints using tags (typically added within the &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#operation-object&#34; target=&#34;_blank&#34;&gt;Operation Object&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;tags:&#xA;  - name: Users&#xA;    description: Operations related to users&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But tags can also be defined at the top-level (i.e. root object).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt; uses the following conventions for its tags which determine how endpoints are documented on Fastly&amp;rsquo;s &lt;a href=&#34;https://developer.fastly.com/reference/api/&#34; target=&#34;_blank&#34;&gt;Developer Hub&lt;/a&gt; (DevHub):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;tags:&#xA;  - name: unlisted # Publish on DevHub at an unlisted URL and exclude from search results&#xA;  - name: excludeFromSearch # Publish on DevHub but exclude from search results&#xA;  - name: internal  # Do not publish on DevHub or build into API clients&#xA;  - name: beta # Display &amp;quot;beta&amp;quot; notice on DevHub&#xA;  - name: limited-availability # Display &amp;quot;LA&amp;quot; notice on DevHub&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#tagObject&#34; target=&#34;_blank&#34;&gt;Tag Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;handling-errors&#34;&gt;Handling Errors&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Communicating errors is crucial in API design, and OpenAPI helps you to define your error responses.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;status-codes&#34;&gt;Status Codes&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Specify status codes and their meanings in your &lt;code&gt;responses&lt;/code&gt; section:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;paths:&#xA;  /users/{userId}:&#xA;    get:&#xA;      responses:&#xA;        &#39;200&#39;:&#xA;          description: Successful response&#xA;        &#39;404&#39;:&#xA;          description: User not found&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;responses&lt;/code&gt; field is a container for the expected responses of an operation. The container maps a HTTP response code (e.g. &lt;code&gt;200&lt;/code&gt; or &lt;code&gt;404&lt;/code&gt; etc) to the expected response.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#responsesObject&#34; target=&#34;_blank&#34;&gt;Responses Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;error-responses&#34;&gt;Error Responses&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can also define error responses with detailed information, and for specific response types:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;responses:&#xA;  &#39;400&#39;:&#xA;    description: Invalid Credit&#xA;    content:&#xA;      application/json:&#xA;        schema:&#xA;          $ref: &#39;#/components/schemas/Error&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we describe a &lt;code&gt;400 Bad Request&lt;/code&gt; error response that will have the &lt;code&gt;Content-Type&lt;/code&gt; of &lt;code&gt;application/json&lt;/code&gt; (i.e. the response will use JSON) and we reference an external schema.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example schema definition that uses the popular &amp;ldquo;Problem Details&amp;rdquo; format from &lt;a href=&#34;https://datatracker.ietf.org/doc/html/rfc7807&#34; target=&#34;_blank&#34;&gt;RFC 7807&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;components:&#xA;  schemas:&#xA;    Error:&#xA;      type: object&#xA;      properties:&#xA;        type:&#xA;          type: string&#xA;          description: A URI reference that identifies the problem type.&#xA;          example: &amp;quot;https://example.com/probs/out-of-credit&amp;quot;&#xA;        title:&#xA;          type: string&#xA;          description: A short, human-readable summary of the problem.&#xA;          example: &amp;quot;You do not have enough credit.&amp;quot;&#xA;        status:&#xA;          type: integer&#xA;          description: The HTTP status code generated by the origin server for this occurrence of the problem.&#xA;          example: 400&#xA;        detail:&#xA;          type: string&#xA;          description: A human-readable explanation specific to this occurrence of the problem.&#xA;          example: &amp;quot;Your current balance is 30, but that costs 50.&amp;quot;&#xA;        instance:&#xA;          type: string&#xA;          description: A URI reference that identifies the specific occurrence of the problem.&#xA;          example: &amp;quot;/account/12345/msgs/abc&amp;quot;&#xA;      required:&#xA;        - type&#xA;        - title&#xA;        - status&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this schema describes is the following example error JSON that a user might see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt; {&#xA;     &amp;quot;type&amp;quot;: &amp;quot;https://example.com/probs/out-of-credit&amp;quot;,&#xA;     &amp;quot;title&amp;quot;: &amp;quot;You do not have enough credit.&amp;quot;,&#xA;     &amp;quot;detail&amp;quot;: &amp;quot;Your current balance is 30, but that costs 50.&amp;quot;,&#xA;     &amp;quot;instance&amp;quot;: &amp;quot;/account/12345/msgs/abc&amp;quot;,&#xA;     &amp;quot;balance&amp;quot;: 30,&#xA;     &amp;quot;accounts&amp;quot;: [&amp;quot;/account/12345&amp;quot;, &amp;quot;/account/67890&amp;quot;]&#xA; }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;REF:&lt;/strong&gt; &lt;a href=&#34;https://spec.openapis.org/oas/v3.0.3#responseObject&#34; target=&#34;_blank&#34;&gt;Response Object&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;testing-and-validation&#34;&gt;Testing and Validation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Ensure the reliability of your API by testing and validating it using OpenAPI tools.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;tools-for-validation&#34;&gt;Tools for Validation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OpenAPI supports validating your API against the defined schemas using a variety of tools, such as &lt;a href=&#34;https://swagger.io/tools/swagger-inspector/&#34; target=&#34;_blank&#34;&gt;Swagger Inspector&lt;/a&gt; and &lt;a href=&#34;https://stoplight.io/open-source/spectral&#34; target=&#34;_blank&#34;&gt;Spectral&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generating-client-sdks&#34;&gt;Generating Client SDKs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Using OpenAPI also helps with generating (and maintaining) client SDKs by using tools like &lt;a href=&#34;https://swagger.io/tools/swagger-codegen/&#34; target=&#34;_blank&#34;&gt;Swagger Codegen&lt;/a&gt; and &lt;a href=&#34;https://openapi-generator.tech/&#34; target=&#34;_blank&#34;&gt;OpenAPI-Generator&lt;/a&gt; to accelerate development for various programming languages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve written about this process on the &lt;a href=&#34;https://dev.to/fastly&#34; target=&#34;_blank&#34;&gt;Fastly dev.to blog&lt;/a&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://dev.to/fastly/better-fastly-api-clients-with-openapi-generator-3lno&#34; target=&#34;_blank&#34;&gt;Better Fastly API clients with OpenAPI Generator&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Embracing OpenAPI as a core component of your API development process can lead to more efficient, well-documented, and collaborative projects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By understanding the key sections of an OpenAPI document and leveraging its capabilities, you can create APIs that are not only robust but also user-friendly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whether you&amp;rsquo;re a solo developer or part of a large team, OpenAPI is a powerful tool that simplifies API design and documentation, ultimately contributing to a better developer experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this brief guide, I&amp;rsquo;ve explored the importance of OpenAPI in API development, discussed its benefits, and walked you through the process of writing an OpenAPI document.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By breaking down the essential sections and providing practical examples, I hope you feel empowered to leverage OpenAPI for your next API project. Happy API designing!&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/openapi/</guid>
      <link>https://www.integralist.co.uk/posts/openapi/</link>
      <pubDate>Fri, 18 Aug 2023 00:00:00 +0000</pubDate>
      <title>The Power of OpenAPI: Simplifying API Design and Documentation</title>
    </item>
    <item>
      <description>&lt;p&gt;You have an API and you want your customers to be able to use that API via &lt;a href=&#34;https://www.terraform.io&#34; target=&#34;_blank&#34;&gt;Terraform&lt;/a&gt;. In this post I&amp;rsquo;m going to explain how you can write your own Terraform provider to enable your customers to integrate your API into their &amp;ldquo;infrastructure as code&amp;rdquo; pipeline.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t need an API to be able to follow along, nor am I going to make you write one as part of the learning process (that&amp;rsquo;s just a waste of time). Instead I&amp;rsquo;m going to demonstrate how a Terraform provider works by talking through the code for an example provider I&amp;rsquo;ve written.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You can find my &amp;lsquo;mock&amp;rsquo; provider &lt;a href=&#34;https://github.com/integralist/terraform-provider-mock&#34; target=&#34;_blank&#34;&gt;here on GitHub&lt;/a&gt; if you&amp;rsquo;d prefer to read the code yourself. It&amp;rsquo;s heavily commented to make it as easy as possible.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The idea is that once you finish reading this post, you should (in theory) be able to just copy my mock provider code base and start adding in your own &lt;em&gt;real&lt;/em&gt; API calls rather than using the stubbed data I&amp;rsquo;ve provided for the sake of keeping the example provider simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In case you&amp;rsquo;re interested, I am the maintainer for the popular &lt;a href=&#34;https://github.com/fastly/terraform-provider-fastly&#34; target=&#34;_blank&#34;&gt;Fastly Terraform provider&lt;/a&gt; (which demonstrates a much more &lt;em&gt;complex&lt;/em&gt; provider). If you want to know how to use the Fastly Terraform provider, then you&amp;rsquo;re in luck as I&amp;rsquo;ve written about that subject on the Fastly blog &lt;a href=&#34;https://www.fastly.com/blog/how-to-configure-your-fastly-services-with-terraform&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; as well as written a Terraform &amp;lsquo;best practices&amp;rsquo; guide on the Fastly Developer Hub &lt;a href=&#34;https://developer.fastly.com/learning/integrations/orchestration/terraform/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; (which is definitely worth checking out).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I should also be clear and say that this isn&amp;rsquo;t a &amp;lsquo;complete&amp;rsquo; guide. There are many aspects to writing a Terraform provider I will gloss over or omit entirely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That all said, let&amp;rsquo;s get started&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;prerequisite&#34;&gt;Prerequisite&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve presumed the reader:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Is familiar with the &lt;a href=&#34;https://go.dev&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; programming language and how to write programs with it.&lt;/li&gt;&#xA;&lt;li&gt;Is familiar with what &lt;a href=&#34;https://www.terraform.io&#34; target=&#34;_blank&#34;&gt;Terraform&lt;/a&gt; is (and ideally has used it before).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;go-mod&#34;&gt;go.mod&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the &lt;em&gt;direct&lt;/em&gt; dependencies needed by my &amp;lsquo;mock&amp;rsquo; provider:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go.mod&#34;&gt;go 1.19&#xA;&#xA;require (&#xA;    github.com/google/uuid v1.3.0&#xA;    github.com/hashicorp/terraform-plugin-docs v0.13.0&#xA;    github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first dependency &lt;a href=&#34;https://github.com/google/uuid&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;google/uuid&lt;/code&gt;&lt;/a&gt; is only used because I needed a quick and convenient way to generate a unique ID (as we&amp;rsquo;ll see later on), while the &lt;a href=&#34;https://github.com/hashicorp/terraform-plugin-docs&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;hashicorp/terraform-plugin-docs&lt;/code&gt;&lt;/a&gt; dependency is only used for the sake of generating documentation from your provider code (a really useful tool actually so you should definitely check it out).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The last dependency, &lt;a href=&#34;https://github.com/hashicorp/terraform-plugin-sdk&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;hashicorp/terraform-plugin-sdk&lt;/code&gt;&lt;/a&gt;, is what fundamentally enables a Terraform provider to work like it does.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hashicorp is working on a replacement to the terraform-plugin-sdk called the &lt;a href=&#34;https://github.com/hashicorp/terraform-plugin-framework&#34; target=&#34;_blank&#34;&gt;Terraform Plugin Framework&lt;/a&gt;. I&amp;rsquo;ve not yet played with the new SDK, so I may well write a follow-up post where I migrate my mock provider to this new framework and/or do so for the Fastly Terraform provider, from which I&amp;rsquo;ll share any useful lessons learned.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;It&amp;rsquo;s worth clarifying that the terraform-plugin-sdk isn&amp;rsquo;t going anywhere any time soon and in the meantime Hashicorp provides guidelines for &lt;a href=&#34;https://developer.hashicorp.com/terraform/plugin/which-sdk&#34; target=&#34;_blank&#34;&gt;which SDK you should use&lt;/a&gt;, so I recommend reading that if you&amp;rsquo;re unsure of which route to take.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I have since discovered there is a &amp;lsquo;scaffold&amp;rsquo; project that Hashicorp provides here &lt;a href=&#34;https://github.com/hashicorp/terraform-provider-scaffolding&#34; target=&#34;_blank&#34;&gt;https://github.com/hashicorp/terraform-provider-scaffolding&lt;/a&gt; that is similar to my mock provider! So I would recomend, once you finish reading this post, giving that a read to see how their hierarchy compares to my mock provider (there&amp;rsquo;s also one for the new plugin framework, which I&amp;rsquo;ll be checking out: &lt;a href=&#34;https://github.com/hashicorp/terraform-provider-scaffolding-framework&#34; target=&#34;_blank&#34;&gt;https://github.com/hashicorp/terraform-provider-scaffolding-framework&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;main-go&#34;&gt;main.go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s take a look at our &lt;code&gt;main&lt;/code&gt; package entry point, which is &amp;lsquo;short and sweet&amp;rsquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;github.com/hashicorp/terraform-plugin-sdk/v2/plugin&amp;quot;&#xA;    &amp;quot;github.com/integralist/terraform-provider-mock/mock&amp;quot;&#xA;)&#xA;&#xA;&#xA;func main() {&#xA;    plugin.Serve(&amp;amp;plugin.ServeOpts{&#xA;        ProviderFunc: mock.Provider,&#xA;    })&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We import the SDK&amp;rsquo;s &lt;a href=&#34;https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.0/plugin&#34; target=&#34;_blank&#34;&gt;plugin&lt;/a&gt; package and call the &lt;a href=&#34;https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2@v2.24.0/plugin#Serve&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Serve&lt;/code&gt;&lt;/a&gt; function, telling it where to find our provider (i.e. &lt;code&gt;mock.Provider&lt;/code&gt;) which is where we define the structure of our Terraform provider.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following implementation of my mock provider is small because, well, my mock provider is small (by design), where as you&amp;rsquo;ll find real-world providers to be a lot larger than this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Provider() *schema.Provider {&#xA;    return &amp;amp;schema.Provider{&#xA;        Schema: map[string]*schema.Schema{&#xA;            &amp;quot;foo&amp;quot;: {&#xA;                Type:        schema.TypeString,&#xA;                Optional:    true,&#xA;                DefaultFunc: schema.EnvDefaultFunc(&amp;quot;MOCK_FOO&amp;quot;, nil),&#xA;            },&#xA;        },&#xA;        ResourcesMap: map[string]*schema.Resource{&#xA;            &amp;quot;mock_example&amp;quot;: resourceExample(),&#xA;        },&#xA;        DataSourcesMap: map[string]*schema.Resource{&#xA;            &amp;quot;mock_example&amp;quot;: dataSourceExample(),&#xA;        },&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So there two parts to a Terraform provider, which will help to explain the above chunk of code:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt;: A resource is a &amp;lsquo;thing&amp;rsquo; you create, and then manage its life cycle via Terraform.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Data Sources&lt;/strong&gt;: A data source is data you can query and reference within your resources.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The following diagram is one I designed for the &lt;a href=&#34;https://www.fastly.com/blog/how-to-configure-your-fastly-services-with-terraform&#34; target=&#34;_blank&#34;&gt;Fastly blog post&lt;/a&gt; I mentioned earlier, and it does a good job visualising the overall Terraform workflow coordination between your terminal shell, the Terraform CLI and the Terraform provider itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/terraform-workflow.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/terraform-workflow.png&#34; alt=&#34;terraform workflow&#34; /&gt;&lt;/a&gt;&#xA;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;A data source is actually a &lt;em&gt;subset&lt;/em&gt; of a resource. This will become apparent shortly when we discuss CRUD (Create, Read, Update, Delete) operations.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Looking at the above code, the first thing we do is define a provider (&lt;code&gt;schema.Provider&lt;/code&gt;) and its &amp;lsquo;schema&amp;rsquo; (&lt;code&gt;schema.Schema&lt;/code&gt;). In the case of our mock provider we actually have a super simple provider schema, it&amp;rsquo;s just a single &amp;lsquo;attribute&amp;rsquo; called &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example of what that would look like in a consumer&amp;rsquo;s Terraform configuration:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;provider &amp;quot;mock&amp;quot; {&#xA;  foo = &amp;quot;example_value&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Because of the &lt;code&gt;DefaultFunc&lt;/code&gt; field in our schema, if &lt;code&gt;foo&lt;/code&gt; wasn&amp;rsquo;t set in the above example configuration, then the value would default to the value assigned to the environment variable &lt;code&gt;MOCK_FOO&lt;/code&gt; (or &lt;code&gt;nil&lt;/code&gt; if the environment variable wasn&amp;rsquo;t set).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically the provider&amp;rsquo;s schema is for defining top-level attributes such as an API key or API endpoint. Take a look at the Fastly Terraform provider for an example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Provider() *schema.Provider {&#xA;    provider := &amp;amp;schema.Provider{&#xA;        Schema: map[string]*schema.Schema{&#xA;            &amp;quot;api_key&amp;quot;: {&#xA;                Type:        schema.TypeString,&#xA;                Optional:    true,&#xA;                DefaultFunc: schema.EnvDefaultFunc(&amp;quot;FASTLY_API_KEY&amp;quot;, nil),&#xA;                Description: &amp;quot;Fastly API Key from https://app.fastly.com/#account&amp;quot;,&#xA;            },&#xA;            &amp;quot;base_url&amp;quot;: {&#xA;                Type:        schema.TypeString,&#xA;                Optional:    true,&#xA;                DefaultFunc: schema.EnvDefaultFunc(&amp;quot;FASTLY_API_URL&amp;quot;, gofastly.DefaultEndpoint),&#xA;                Description: &amp;quot;Fastly API URL&amp;quot;,&#xA;            },&#xA;            &amp;quot;force_http2&amp;quot;: {&#xA;                Type:        schema.TypeBool,&#xA;                Optional:    true,&#xA;                Default:     false,&#xA;                Description: &amp;quot;Set this to `true` to disable HTTP/1.x fallback mechanism&amp;quot;&#xA;            },&#xA;            &amp;quot;no_auth&amp;quot;: {&#xA;                Type:        schema.TypeBool,&#xA;                Optional:    true,&#xA;                Default:     false,&#xA;                Description: &amp;quot;Set to `true` if your config consumes data without auth&amp;quot;,&#xA;            },&#xA;        },&#xA;&#xA;    ...&#xA;  }&#xA;&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now there&amp;rsquo;s one aspect to our provider that I&amp;rsquo;ve omitted and that&amp;rsquo;s the &lt;code&gt;ConfigureFunc&lt;/code&gt; field. Because my mock provider doesn&amp;rsquo;t have a real API to use I&amp;rsquo;ve not defined that field in my mock provider but here is an example from the Fastly Terraform provider to give you an idea of what it could look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Provider() *schema.Provider {&#xA;    provider := &amp;amp;schema.Provider{&#xA;        Schema: map[string]*schema.Schema{&#xA;      // ...&#xA;        },&#xA;        DataSourcesMap: map[string]*schema.Resource{&#xA;            // ...&#xA;        },&#xA;        ResourcesMap: map[string]*schema.Resource{&#xA;            // ...&#xA;        },&#xA;    }&#xA;&#xA;    provider.ConfigureContextFunc = func(_ context.Context, d *schema.ResourceData) (any, diag.Diagnostics) {&#xA;        config := Config{&#xA;            APIKey:     d.Get(&amp;quot;api_key&amp;quot;).(string),&#xA;            BaseURL:    d.Get(&amp;quot;base_url&amp;quot;).(string),&#xA;            NoAuth:     d.Get(&amp;quot;no_auth&amp;quot;).(bool),&#xA;            ForceHTTP2: d.Get(&amp;quot;force_http2&amp;quot;).(bool),&#xA;            UserAgent:  provider.UserAgent(TerraformProviderProductUserAgent, version.ProviderVersion),&#xA;        }&#xA;        return config.Client()&#xA;    }&#xA;&#xA;    return provider&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the Fastly Terraform provider you can see the &lt;code&gt;ConfigureContextFunc&lt;/code&gt; (there are &amp;lsquo;context&amp;rsquo; aware versions of most functions) we return a &lt;code&gt;config.Client()&lt;/code&gt; which is effectively the Fastly API client. I&amp;rsquo;ll come back to this later when we look at the CREATE function of a resource to show you how you can get access to this API client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For now, let&amp;rsquo;s jump back to our mock provider to remind ourselves of what was configured after the &lt;code&gt;Schema&lt;/code&gt; field&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;ResourcesMap: map[string]*schema.Resource{&#xA;    &amp;quot;mock_example&amp;quot;: resourceExample(),&#xA;},&#xA;DataSourcesMap: map[string]*schema.Resource{&#xA;    &amp;quot;mock_example&amp;quot;: dataSourceExample(),&#xA;},&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So now we have a basic understanding of what a &amp;lsquo;resource&amp;rsquo; is and what a &amp;lsquo;data source&amp;rsquo; is, we can clearly see that a Terraform provider can be setup with &lt;em&gt;multiple&lt;/em&gt; of each type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The interesting part here is that there is a &amp;lsquo;convention over configuration&amp;rsquo; style pattern at play here. Specifically, the map key has to be of the format &lt;code&gt;&amp;lt;provider_name&amp;gt;_&amp;lt;resource|data_source&amp;gt;&lt;/code&gt;, and in my mock provider I only have one resource and one data source and I name them the same &lt;code&gt;mock_example&lt;/code&gt; (as &amp;lsquo;mock&amp;rsquo; is the name of my provider, and &amp;lsquo;example&amp;rsquo; is the resource/data-source name).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of the resource, the provider will attempt to resolve the function assigned to the map key by looking up the file &lt;code&gt;resource_&amp;lt;provider_name&amp;gt;_&amp;lt;resource_name&amp;gt;.go&lt;/code&gt;, i.e. &lt;code&gt;resource_mock_example.go&lt;/code&gt; while it will attempt to resolve the data source using &lt;code&gt;data_source_&amp;lt;provider_name&amp;gt;_&amp;lt;data_source_name&amp;gt;&lt;/code&gt;, i.e. &lt;code&gt;data_source_mock_example.go&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at the tree structure of my mock provider we&amp;rsquo;ll see that&amp;rsquo;s exactly what it contains:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;.&#xA;├── main.go&#xA;├── mock&#xA;│   ├── data_source_mock_example.go&#xA;│   ├── provider.go&#xA;│   └── resource_mock_example.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, all good so far. Now let&amp;rsquo;s get into the meat of these two files, what exactly do they do?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, firstly the &amp;lsquo;example&amp;rsquo; resource defines its own schema (e.g. the attributes it contains) and it also specifies CRUD operation functions (i.e. Create, Read, Update, Delete) for managing the life cycle of the resource. In our mock provider it looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func resourceExample() *schema.Resource {&#xA;    return &amp;amp;schema.Resource{&#xA;        Create: resourceCreate,&#xA;        Read:   resourceRead,&#xA;        Update: resourceUpdate,&#xA;        Delete: resourceDelete,&#xA;&#xA;        Schema: map[string]*schema.Schema{&#xA;            &amp;quot;last_updated&amp;quot;: {&#xA;                Type:     schema.TypeString,&#xA;                Computed: true,&#xA;            },&#xA;            &amp;quot;not_computed_optional&amp;quot;: {&#xA;                Type:     schema.TypeString,&#xA;                Optional: true,&#xA;            },&#xA;            &amp;quot;not_computed_required&amp;quot;: {&#xA;                Type:     schema.TypeString,&#xA;                Required: true,&#xA;            },&#xA;            &amp;quot;foo&amp;quot;: {&#xA;                Type:     schema.TypeList,&#xA;                Optional: true,&#xA;                Elem: &amp;amp;schema.Resource{&#xA;                    Schema: map[string]*schema.Schema{&#xA;                        &amp;quot;bar&amp;quot;: {&#xA;                            Type:     schema.TypeList,&#xA;                            MaxItems: 1,&#xA;                            Required: true,&#xA;                            Elem: &amp;amp;schema.Resource{&#xA;                                Schema: map[string]*schema.Schema{&#xA;                                    &amp;quot;number&amp;quot;: {&#xA;                                        Type:     schema.TypeInt,&#xA;                                        Optional: true,&#xA;                                    },&#xA;                                    &amp;quot;version&amp;quot;: {&#xA;                                        Type:     schema.TypeString,&#xA;                                        Computed: true,&#xA;                                    },&#xA;                                },&#xA;                            },&#xA;                        },&#xA;                    },&#xA;                },&#xA;            },&#xA;            &amp;quot;baz&amp;quot;: {&#xA;                Type:     schema.TypeList,&#xA;                Required: true,&#xA;                Elem: &amp;amp;schema.Resource{&#xA;                    Schema: map[string]*schema.Schema{&#xA;                        &amp;quot;qux&amp;quot;: {&#xA;                            Type:     schema.TypeString,&#xA;                            Required: true,&#xA;                        },&#xA;                    },&#xA;                },&#xA;            },&#xA;            &amp;quot;some_list&amp;quot;: {&#xA;                Type:     schema.TypeList,&#xA;                Optional: true,&#xA;                Elem: &amp;amp;schema.Schema{&#xA;                    Type: schema.TypeString,&#xA;                },&#xA;            },&#xA;        },&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are a few things to pay attention to in this schema:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;last_updated&lt;/code&gt; is a &amp;lsquo;computed&amp;rsquo; attribute, meaning the user shouldn&amp;rsquo;t attempt to set that in their configuration but instead leave it to the Terraform provider to set it dynamically. A user would then use &lt;a href=&#34;https://developer.hashicorp.com/terraform/language/values/outputs&#34; target=&#34;_blank&#34;&gt;output variables&lt;/a&gt; to access the value set by the provider.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;not_computed_required&lt;/code&gt;: is marked as &amp;lsquo;required&amp;rsquo; and so a user of our provider &lt;em&gt;must&lt;/em&gt; set this attribute, while other attributes are marked as &amp;lsquo;optional&amp;rsquo;.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;foo&lt;/code&gt; has a type of &lt;code&gt;TypeList&lt;/code&gt;, meaning we need to define what schema its &amp;lsquo;elements&amp;rsquo; should have. We use &lt;code&gt;Elem&lt;/code&gt; to specify there should be a nested &lt;code&gt;bar&lt;/code&gt; block, which itself contains &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt; attributes (the latter being a &amp;lsquo;computed&amp;rsquo; attribute).&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In terms of a consumer of our Terraform provider, someone might write their configuration like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;quot;mock_example&amp;quot; &amp;quot;testing&amp;quot; {&#xA;  not_computed_required = &amp;quot;some value&amp;quot;&#xA;&#xA;  foo {&#xA;    bar {&#xA;      number = 1&#xA;    }&#xA;  }&#xA;  foo {&#xA;    bar {&#xA;      number = 2&#xA;    }&#xA;  }&#xA;  foo {&#xA;    bar {&#xA;      number = 3&#xA;    }&#xA;  }&#xA;&#xA;  baz {&#xA;    qux = &amp;quot;x&amp;quot;&#xA;  }&#xA;  baz {&#xA;    qux = &amp;quot;y&amp;quot;&#xA;  }&#xA;  baz {&#xA;    qux = &amp;quot;z&amp;quot;&#xA;  }&#xA;&#xA;  some_list = [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example the user has set the attribute &lt;code&gt;not_computed_required&lt;/code&gt; because it was marked as &amp;lsquo;required&amp;rsquo; in our provider schema, while providing multiple instances of the optional &lt;code&gt;foo&lt;/code&gt; block, and multiple instances of the required &lt;code&gt;bar&lt;/code&gt; blocks. The &lt;code&gt;some_list&lt;/code&gt; attribute is also provided, although it&amp;rsquo;s marked as &amp;lsquo;optional&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth noting the above configuration can, through clever use of the Terraform Configuration Language (TCL), be made more concise/dynamic&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;quot;mock_example&amp;quot; &amp;quot;testing&amp;quot; {&#xA;  not_computed_required = &amp;quot;some value&amp;quot;&#xA;&#xA;  dynamic &amp;quot;foo&amp;quot; {&#xA;    for_each = [{ number = 1 }, { number = 2 }, { number = 3 }]&#xA;    content {&#xA;      bar {&#xA;        number = foo.value.number&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  dynamic &amp;quot;baz&amp;quot; {&#xA;    for_each = [{ something = &amp;quot;x&amp;quot; }, { something = &amp;quot;y&amp;quot; }, { something = &amp;quot;z&amp;quot; }]&#xA;    content {&#xA;      qux = baz.value.something&#xA;    }&#xA;  }&#xA;&#xA;  some_list = [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;but this blog post isn&amp;rsquo;t about TCL so I&amp;rsquo;d recommend reading the official Terraform documentation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now look back at the CRUD functions for our resource:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;Create: resourceCreate,&#xA;Read:   resourceRead,&#xA;Update: resourceUpdate,&#xA;Delete: resourceDelete,&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;These functions are called at specific times depending on what &lt;code&gt;terraform&lt;/code&gt; CLI command was executed by a user, and also depending on what state their project is in at the time the command is executed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, running &lt;code&gt;terraform apply&lt;/code&gt; for the first time will cause the &amp;lsquo;Create&amp;rsquo; function to be called (so all the relevant resources defined in the user&amp;rsquo;s configuration will be created), followed (typically) by the &amp;lsquo;Read&amp;rsquo; function (so that the user&amp;rsquo;s local project state will be updated with the new resources created via the &amp;lsquo;Create&amp;rsquo; function).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next time the user runs &lt;code&gt;terraform apply&lt;/code&gt; they&amp;rsquo;ll find Terraform will trigger the &amp;lsquo;Read&amp;rsquo; function to execute first (so that Terraform can update the project state and know if anything has changed), before then determining if the &amp;lsquo;Update&amp;rsquo; function needs to be called, because let&amp;rsquo;s say the user has modified their configuration in such a way as to require one of the resources defined to be updated (e.g. to make API calls on our behalf).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now look at each CRUD function individually&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;create&#34;&gt;Create&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The CREATE operation typically will make API calls to create resources. It won&amp;rsquo;t set anything in the terraform state, with the exception of setting a unique ID that will be used by all the other functions to access the resource data from state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at the code in our &amp;lsquo;mock&amp;rsquo; provider to see what we&amp;rsquo;re doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func resourceCreate(d *schema.ResourceData, m any) error {&#xA;    foo := d.Get(&amp;quot;foo&amp;quot;).([]any)&#xA;    d.SetId(&amp;quot;123&amp;quot;)&#xA;    return resourceRead(d, m)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see the function is passed a &lt;code&gt;schema.ResourceData&lt;/code&gt; type. This is essentially the user&amp;rsquo;s local configuration data, and we can see that the first thing we do is try to get the value of the &lt;code&gt;foo&lt;/code&gt; attribute. It also has a second argument which is effectively additional &amp;lsquo;metadata&amp;rsquo; and is what we would reference in order to get access to our API client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if this was a real provider, then we&amp;rsquo;d have an API client that would be creating an actual resource for the user. Remember earlier we talked about the &lt;code&gt;ConfigureFunc&lt;/code&gt; function of the provider, which was responsible for defining an instance of an API client? Well, the way we get access to the API client would look something like this (where &lt;code&gt;APIClient&lt;/code&gt; is some type that represents your API client):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;client := m.(*APIClient).conn&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Because &lt;code&gt;foo&lt;/code&gt; is a &lt;code&gt;TypeList&lt;/code&gt; you can see we type assert it to &lt;code&gt;[]any&lt;/code&gt;. Now as I said at the start, we don&amp;rsquo;t have an API to make calls to and so we don&amp;rsquo;t actually &lt;em&gt;do&lt;/em&gt; anything here with the &lt;code&gt;foo&lt;/code&gt; value defined in the user&amp;rsquo;s configuration.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s pretend we made an API call, and in the response we got back an ID that we wanted to use as a unique key to track this resource in our terraform state file. To set the unique ID we call &lt;code&gt;d.SetId(&amp;quot;123&amp;quot;)&lt;/code&gt;, where &lt;code&gt;123&lt;/code&gt; is the unique ID we got back from the API response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The mere existence of the ID, and lack of error returned, means Terraform will presume the CREATE operation was successful and store the user&amp;rsquo;s &amp;ldquo;foo&amp;rdquo; data in the local state file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, we call the READ function (&lt;code&gt;resourceRead()&lt;/code&gt;) and pass through the &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;m&lt;/code&gt; arguments. In this case, the way we&amp;rsquo;ve setup our CREATE function means that if the READ operation fails, then the error it returns will be returned through our CREATE function and will cause the create operation to fail as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s up to you whether that&amp;rsquo;s something you want to do, as a READ could fail due to a network issue and not necessarily mean there was an error with the CREATE operation.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;read&#34;&gt;Read&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The READ operation must handle three things:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Calling out to the API to get the latest data for our resource.&lt;/li&gt;&#xA;&lt;li&gt;Flatten the API response (or at least extract the values we need) and marshal the data into a format that Terraform understands (i.e. &lt;code&gt;map[string]any&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Set the latest data into Terraform&amp;rsquo;s state file so it can identify if there were any differences between what the user has defined in their configuration and what actually exists on the remote data side.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at the code in our &amp;lsquo;mock&amp;rsquo; provider to see what we&amp;rsquo;re doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func resourceRead(d *schema.ResourceData, m any) error {&#xA;  resourceID := d.Id()&#xA;  foo := d.Get(&amp;quot;foo&amp;quot;)&#xA;&#xA;  for _, f := range foo.([]any) {&#xA;    f := f.(map[string]any)&#xA;&#xA;    for _, b := range f[&amp;quot;bar&amp;quot;].([]any) {&#xA;      b := b.(map[string]any)&#xA;      b[&amp;quot;version&amp;quot;] = uuid.New().String()&#xA;    }&#xA;  }&#xA;&#xA;  if err := d.Set(&amp;quot;foo&amp;quot;, foo); err != nil {&#xA;    return err&#xA;  }&#xA;&#xA;  d.Set(&amp;quot;last_updated&amp;quot;, time.Now().Format(time.RFC850))&#xA;&#xA;  return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so there&amp;rsquo;s a little more going on here, but nothing too complicated. First thing we do is get the ID we set into the Terraform state after we had initially created the resource (&lt;code&gt;d.Id()&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, because we don&amp;rsquo;t have a real API to get live data from, I&amp;rsquo;m going to hardcode data to be set into terraform state. To do that I&amp;rsquo;m going to get the data out from the Terraform state using &lt;code&gt;d.Get(&amp;quot;foo&amp;quot;)&lt;/code&gt; and I&amp;rsquo;m going to dynamically update the nested &lt;code&gt;version&lt;/code&gt; attribute, which if you remember was defined as a &amp;lsquo;computed&amp;rsquo; value (meaning its an attribute the Terraform provider must set).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But as this is a nested attribute I have to iterate over each parent structure until I reach the relevant level of the data structure where I can then set a value on the &lt;code&gt;version&lt;/code&gt; attribute. That&amp;rsquo;s effectively what the two &lt;code&gt;for&lt;/code&gt; loops are doing, and you&amp;rsquo;ll see this is where the &lt;code&gt;github.com/google/uuid&lt;/code&gt; dependency comes in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once that&amp;rsquo;s done we&amp;rsquo;re able to set the updated data structure into the local state file using &lt;code&gt;d.Set()&lt;/code&gt; and be aware that we can&amp;rsquo;t just set the &lt;code&gt;version&lt;/code&gt; attribute directly, we must set the root &lt;code&gt;foo&lt;/code&gt; attribute and this means constructing its complete data structure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that the &lt;code&gt;last_updated&lt;/code&gt; attribute was also marked as &amp;lsquo;computed&amp;rsquo; as so we need to set that dynamically too (and for that I just set the value using the current timestamp, and to be fair I could of done the same for the &lt;code&gt;version&lt;/code&gt; attribute rather than use an external uuid package).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;update&#34;&gt;Update&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The UPDATE operation is similar to the READ but we typically use additional SDK methods to help us know if there&amp;rsquo;s been a change that would require a modification to the data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at the code in our &amp;lsquo;mock&amp;rsquo; provider to see what we&amp;rsquo;re doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func resourceUpdate(d *schema.ResourceData, m any) error {&#xA;  resourceID := d.Id()&#xA;&#xA;  if d.HasChange(&amp;quot;foo&amp;quot;) {&#xA;    foo := d.Get(&amp;quot;foo&amp;quot;).([]any)&#xA;    d.Set(&amp;quot;last_updated&amp;quot;, time.Now().Format(time.RFC850))&#xA;  }&#xA;&#xA;  return resourceRead(d, m)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So some similar stuff here. First we get the resource&amp;rsquo;s ID with &lt;code&gt;d.Id()&lt;/code&gt; but now we&amp;rsquo;re using &lt;code&gt;d.HasChange()&lt;/code&gt; to see if the &lt;code&gt;foo&lt;/code&gt; attribute has changed, and if it has, then we modify the local state. Of course the mock provider is just setting a value for &lt;code&gt;last_updated&lt;/code&gt; as if there was a change but in reality your real provider would be making an &amp;lsquo;update&amp;rsquo; API call to update the resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, we do a READ operation to be sure we get the updated API changes stored into our local state.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;delete&#34;&gt;Delete&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The DELETE operation is very simple. In order to delete a resource from the local Terraform state we simply need to set the ID for the resource to an empty string&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func resourceDelete(d *schema.ResourceData, m any) error {&#xA;  resourceID := d.Id()&#xA;  d.SetId(&amp;quot;&amp;quot;)&#xA;  return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now in our mock provider you&amp;rsquo;ll see we get the resource ID and although that looks pointless, in a real provider, you would want to get the resource ID because remember you&amp;rsquo;d need to make an API call to delete the resource first before deleting it from the Terraform state.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;data-sources&#34;&gt;Data Sources&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, before we wrap up, let&amp;rsquo;s look at our example data source to see the schema structure:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func dataSourceExample() *schema.Resource {&#xA;    return &amp;amp;schema.Resource{&#xA;        Read: dataSourceRead,&#xA;        Schema: map[string]*schema.Schema{&#xA;            &amp;quot;things&amp;quot;: {&#xA;                Type:     schema.TypeList,&#xA;                Computed: true,&#xA;                Elem: &amp;amp;schema.Resource{&#xA;                    Schema: map[string]*schema.Schema{&#xA;                        &amp;quot;id&amp;quot;: {&#xA;                            Type:     schema.TypeInt,&#xA;                            Computed: true,&#xA;                        },&#xA;                        &amp;quot;version&amp;quot;: {&#xA;                            Type:     schema.TypeString,&#xA;                            Computed: true,&#xA;                        },&#xA;                    },&#xA;                },&#xA;            },&#xA;        },&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So there&amp;rsquo;s a lot of similarities between a &amp;lsquo;resource&amp;rsquo; and a &amp;lsquo;data source&amp;rsquo;, and that&amp;rsquo;s because a data source is a &lt;em&gt;subset&lt;/em&gt; of a resource. So the main difference is we have a READ operation/function but none of the other CRUD functions (e.g. Create, Update, Delete) because a data source is only used for &lt;em&gt;querying&lt;/em&gt; data and not something you create/update/delete.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As far as the schema is concerned we&amp;rsquo;ve defined a &lt;code&gt;things&lt;/code&gt; attribute, which is &amp;lsquo;computed&amp;rsquo; along with all its nested attributes, and that makes sense as this isn&amp;rsquo;t something a user defines in their configuration.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s take a look at the READ function to see what that&amp;rsquo;s doing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func dataSourceRead(d *schema.ResourceData, m any) error {&#xA;    const jsonStream = `&#xA;        [&#xA;            {&amp;quot;id&amp;quot;: 1, &amp;quot;version&amp;quot;: &amp;quot;a&amp;quot;},&#xA;            {&amp;quot;id&amp;quot;: 2, &amp;quot;version&amp;quot;: &amp;quot;b&amp;quot;},&#xA;            {&amp;quot;id&amp;quot;: 3, &amp;quot;version&amp;quot;: &amp;quot;c&amp;quot;},&#xA;        ]`&#xA;&#xA;    things := make([]map[string]any, 0)&#xA;    err := json.NewDecoder(strings.NewReader(jsonStream)).Decode(&amp;amp;things)&#xA;    if err != nil {&#xA;        return err&#xA;    }&#xA;&#xA;    if err := d.Set(&amp;quot;things&amp;quot;, things); err != nil {&#xA;        return err&#xA;    }&#xA;&#xA;    d.SetId(strconv.FormatInt(time.Now().Unix(), 10))&#xA;&#xA;    return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;jsonStream&lt;/code&gt; variable is creating stubbed data. This is as if we had made an actual API call and received back a bunch of data from the API.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for us to store the returned data into Terraform we need to marshal the data into a format that matches what the schema expects (e.g. &lt;code&gt;[]map[string]any&lt;/code&gt;) and in this case we&amp;rsquo;re imagining our API returned JSON formatted data and so we use &lt;code&gt;json.NewDecoder&lt;/code&gt; to decode the API response into the &lt;code&gt;things&lt;/code&gt; variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We then set the &lt;code&gt;things&lt;/code&gt; data back into the local state using &lt;code&gt;d.Set()&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;ve reached the final interesting part, which is the &lt;code&gt;d.SetId()&lt;/code&gt; call. So to explain, we don&amp;rsquo;t have a unique ID for this data resource so we create one using a timestamp format. I typically see people use a hash of the returned API data as a unique key, so pick your poison.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-to-use-this-provider&#34;&gt;How to use this provider&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now if my mock provider was published to the Terraform registry it would be very simple to consume, but I&amp;rsquo;ve not done that because I wanted an opportunity to explain how to test your own provider locally to be sure it&amp;rsquo;s working first.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, to consume this mock provider without it being published to the Terraform registry, follow these steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Clone the repo and build the &lt;code&gt;terraform-provider-mock&lt;/code&gt; binary:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;&#xA;make build&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Create a separate directory for your own Terraform project.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. &lt;code&gt;cd ../ &amp;amp;&amp;amp; mkdir example-tf&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Create a &lt;code&gt;dev.tfrc&lt;/code&gt; file in your own Terraform project&amp;rsquo;s directory:&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-tf&#34;&gt;&#xA;provider_installation {&#xA;dev_overrides {&#xA;  &amp;quot;integralist/mock&amp;quot; = &amp;quot;../terraform-provider-mock&amp;quot; // the directory where the binary was built.&#xA;}&#xA;direct {}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;In that shell instance set the &lt;code&gt;TF_CLI_CONFIG_FILE&lt;/code&gt; environment variable.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. &lt;code&gt;export TF_CLI_CONFIG_FILE=/example-tf/dev.tfrc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Create Terraform project files.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. see the &lt;a href=&#34;https://github.com/Integralist/terraform-provider-mock/blob/main/README.md#example-terraform-consumer-code&#34; target=&#34;_blank&#34;&gt;Example Terraform Consumer Code&lt;/a&gt; in my mock provider&amp;rsquo;s README.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Initialize your Terraform project and then execute a plan.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. &lt;code&gt;terraform init &amp;amp;&amp;amp; terraform plan&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;every time you make a change to the Terraform provider code, you&amp;rsquo;ll need to rebuild the binary and then go to your consuming Terraform project and reinitialize (i.e. &lt;code&gt;terraform init&lt;/code&gt;) so it picks up the latest version of the &lt;code&gt;terraform-provider-mock&lt;/code&gt; binary.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;local-development&#34;&gt;Local Development&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When running:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ TF_LOG=TRACE terraform init&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should notice a couple of things different from what you&amp;rsquo;d normally see when initializing a new Terraform project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first is a message highlighting the fact that a provider &amp;lsquo;override&amp;rsquo; is in place:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;Warning: Provider development overrides are in effect&#xA;&#xA;The following provider development overrides are set in the CLI configuration:&#xA; - integralist/mock in /Users/integralist/Code/terraform/terraform-provider-mock&#xA;&#xA;The behavior may therefore not match any released version of the provider and&#xA;applying changes may cause the state to become incompatible with published&#xA;releases.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That is expected in this case we&amp;rsquo;ve followed the instructions above, which tells us how to implement an override for the sake of local testing of the provider code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The other thing you&amp;rsquo;ll notice is an error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;Error: Failed to query available provider packages&#xA;&#xA;Could not retrieve the list of available versions for provider&#xA;integralist/mock: provider registry registry.terraform.io does not have a&#xA;provider named registry.terraform.io/integralist/mock&#xA;&#xA;If you have just upgraded directly from Terraform v0.12 to Terraform v0.14&#xA;then please upgrade to Terraform v0.13 first and follow the upgrade guide for&#xA;that release, which might help you address this problem.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This error is expected because we&amp;rsquo;ve not actually published this provider to the Terraform registry, so indeed it cannot be found. But the error doesn&amp;rsquo;t prevent you from consuming the local provider binary still.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t use &lt;code&gt;Print&lt;/code&gt; functions from the &lt;code&gt;fmt&lt;/code&gt; package in the Terraform provider as, depending on the execution flow, Terraform can treat it as input to its internal program and treat it as an error. So use &lt;code&gt;Print&lt;/code&gt; functions from the &lt;code&gt;log&lt;/code&gt; package instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I&amp;rsquo;ve since discovered &lt;a href=&#34;https://pkg.go.dev/github.com/hashicorp/terraform-plugin-log/tflog&#34; target=&#34;_blank&#34;&gt;https://pkg.go.dev/github.com/hashicorp/terraform-plugin-log/tflog&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;debugging-a-terraform-provider&#34;&gt;Debugging a Terraform Provider&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are essentially two approaches:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Log-Based Debugging&lt;/li&gt;&#xA;&lt;li&gt;Debugger-Based Debugging.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Refer to the &lt;a href=&#34;https://www.terraform.io/plugin/sdkv2/debugging&#34; target=&#34;_blank&#34;&gt;official Hashicorp plugin documentation&lt;/a&gt; and also the &lt;a href=&#34;https://github.com/fastly/terraform-provider-fastly#debugging-the-provider&#34; target=&#34;_blank&#34;&gt;Fastly Terraform provider&lt;/a&gt; documents, which demonstrates the latter approach.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There we have it! A simple Terraform provider broken down as simply as I could manage.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hopefully you can now mentally model your own API into a provider for your users.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/terraform-build-a-provider/</guid>
      <link>https://www.integralist.co.uk/posts/terraform-build-a-provider/</link>
      <pubDate>Sat, 12 Nov 2022 00:00:00 +0000</pubDate>
      <title>Beginner&#39;s guide to creating a Terraform Provider</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The five types covered: &lt;code&gt;Box&lt;/code&gt;, &lt;code&gt;Rc&lt;/code&gt;, &lt;code&gt;Arc&lt;/code&gt;, &lt;code&gt;Cell&lt;/code&gt;, &lt;code&gt;RefCell&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Not discussed are &lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;RwLock&amp;lt;T&amp;gt;&lt;/code&gt;,&lt;br&gt;&#xA;which provide mutual-exclusion.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;: A pointer type for heap allocation.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt;: Single-threaded &amp;lsquo;multiple owners&amp;rsquo; pointer (immutable).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;: Thread-safe &amp;lsquo;multiple owners&amp;rsquo; pointer (immutable).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt;: Single-threaded mutability for &lt;code&gt;Copy&lt;/code&gt; types.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt;: Single-threaded mutability for reference types.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;quick-notes&#34;&gt;Quick notes&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; both support mutability by wrapping the inner value with another type. &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; for &lt;code&gt;Rc&lt;/code&gt;, and &lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;RwLock&amp;lt;T&amp;gt;&lt;/code&gt; or one of the &lt;code&gt;Atomic*&lt;/code&gt; types for &lt;code&gt;Arc&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;&amp;rsquo;s thread-safety comes at a cost: additional performance overhead.&lt;br&gt;&#xA;So choose &lt;code&gt;Rc&lt;/code&gt; whenever possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; behaves like an exclusive borrow, aka a &lt;code&gt;&amp;amp;mut T&lt;/code&gt; (meaning the compiler won&amp;rsquo;t let you have multiple mutable borrows), while &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; removes the compile-time borrow-checks so that it can provide more flexibility than &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; has (which is constrained to &lt;code&gt;Copy&lt;/code&gt; types only).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Subsequently &lt;code&gt;RefCell&lt;/code&gt; introduces the possibility of ending up with multiple mutable borrows. The borrow rules for &lt;code&gt;RefCell&lt;/code&gt; aren&amp;rsquo;t statically checked at compile time but dynamically checked at &lt;em&gt;runtime&lt;/em&gt;, which means this type is capable of triggering a panic if multiple mutable borrows is detected.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;important&#34;&gt;IMPORTANT&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m not the author of the &lt;em&gt;following&lt;/em&gt; content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My own summary/quick notes (above) are sufficient for my own reference, but in case it&amp;rsquo;s not, then the following content may be useful to you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Rather than link off to various intertwined documentation pages, with lots of extra cruft that can muddy the essentials of what you need to know. I read through the official Rust documentation and cherry-picked useful subsets of that information and grouped it in a way that helped me to more easily make sense of the topic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means I take no credit for the following content.&lt;br&gt;&#xA;It was written by many people much smarter than me.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;context&#34;&gt;Context&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &lt;em&gt;pointer&lt;/em&gt; is a general concept for a variable that contains an address in memory. This address refers to, or “points at,” some other data. The most common kind of pointer in Rust is a reference. References are indicated by the &amp;amp; symbol and borrow the value they point to. They don’t have any special capabilities other than referring to data, and have no overhead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Smart pointers&lt;/em&gt;, on the other hand, are data structures that act like a pointer but also have additional metadata and capabilities.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Both &lt;code&gt;String&lt;/code&gt; and &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; types count as smart pointers because they own some memory and allow you to manipulate it. They also have metadata and extra capabilities or guarantees.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Smart pointers are usually implemented using structs. Unlike an ordinary struct, smart pointers implement the &lt;code&gt;Deref&lt;/code&gt; and &lt;code&gt;Drop&lt;/code&gt; traits. The &lt;code&gt;Deref&lt;/code&gt; trait allows an instance of the smart pointer struct to behave like a reference so you can write your code to work with either references or smart pointers. The &lt;code&gt;Drop&lt;/code&gt; trait allows you to customize the code that&amp;rsquo;s run when an instance of the smart pointer goes out of scope.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;box-t&#34;&gt;&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Boxes allow you to store data on the heap rather than the stack. What remains on the stack is the pointer to the heap data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Usage:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When you have a type whose size can’t be known at compile time and you want to use a value of that type in a context that requires an exact size (e.g. recursive data types).&lt;/li&gt;&#xA;&lt;li&gt;When you have a large amount of data and you want to transfer ownership but ensure the data won’t be copied when you do so (e.g. only the small amount of pointer data is copied around on the stack, while the data it references stays in one place on the heap).&lt;/li&gt;&#xA;&lt;li&gt;When you want to own a value and you care only that it’s a type that implements a particular trait rather than being of a specific type (i.e. &lt;em&gt;trait objects&lt;/em&gt; used for dynamic dispatch).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;rc-t&#34;&gt;&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This type is an abbreviation for &lt;em&gt;reference counting&lt;/em&gt; and it enables multiple ownership. It lets us have multiple “owning” pointers to the same data, and the data will be freed (destructors will be run) when all pointers are out of scope.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We use the &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; type when we want to allocate some data on the heap for multiple parts of our program to read and we can’t determine at compile time which part will finish using the data last.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; is only for use in single-threaded scenarios. When shared ownership between threads is needed, &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; (Atomic Reference Counted) can be used.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;arc-t&#34;&gt;&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The same as &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; but thread-safe (it has the same API as &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; to make them interchangeable). But thread-safety comes with a performance cost so if you don&amp;rsquo;t need thread-safety, then definitely opt for &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; instead.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;cell-t-refcell-t&#34;&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt;/&lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Rust memory safety is based on this rule: Given an object &lt;code&gt;T&lt;/code&gt;, it is only possible to have one of the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Having several immutable references (&lt;code&gt;&amp;amp;T&lt;/code&gt;) to the object.&lt;/li&gt;&#xA;&lt;li&gt;Having one mutable reference (&lt;code&gt;&amp;amp;mut T&lt;/code&gt;) to the object.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This rule can be bent using &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; and is referred to as &lt;em&gt;interior mutability&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; implements interior mutability by moving values in and out of the &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt;. To use references instead of values, use the &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; type, and acquire a write lock before mutating.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Borrows for &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt;s are tracked &lt;em&gt;at runtime&lt;/em&gt;, unlike Rust’s native reference types which are entirely tracked statically, at compile time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; borrows are &lt;em&gt;dynamic&lt;/em&gt; it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in thread panic.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Neither &lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;/code&gt; nor &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; are thread-safe.&lt;br&gt;&#xA;The &lt;code&gt;Sync&lt;/code&gt; marker trait is not implemented.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Many shared smart pointer types, including &lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt; and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;, provide containers that can be cloned and shared between multiple parties. The contained values can only be borrowed with &lt;code&gt;&amp;amp;&lt;/code&gt;, not &lt;code&gt;&amp;amp;mut&lt;/code&gt;. Without cells it would be impossible to mutate data inside of these smart pointers at all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s very common then to put a &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; inside shared pointer types to reintroduce mutability. But as &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt;s are for single-threaded scenarios, consider using &lt;code&gt;RwLock&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt; instead of &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;/code&gt; if you need shared mutability in a multi-threaded situation.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/rust-smart-pointers/</guid>
      <link>https://www.integralist.co.uk/posts/rust-smart-pointers/</link>
      <pubDate>Mon, 20 Jun 2022 00:00:00 +0000</pubDate>
      <title>Rust Smart Pointers</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is the second edition to &lt;a href=&#34;/posts/laptop-setup/&#34;&gt;&amp;ldquo;New Laptop Configuration&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;backup&#34;&gt;Backup&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When moving laptops I will temporarily backup my existing GPG and SSH keys (encrypted) to an external data storage device.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We start by making a directory to hold the files temporarily:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir /tmp/keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next I start backing up my GPG data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;# Export the secret key that encrypts all the data in my &#39;password store&#39;.&#xA;# I encode the binary data in a ASCII armored file (.asc).&#xA;gpg --export-secret-keys --armor &amp;lt;NAME&amp;gt; &amp;gt; /tmp/keys/&amp;lt;NAME&amp;gt;.asc&#xA;&#xA;# Once exported I add a password to the file so people are unable to open it.&#xA;# This will produce a .asc.gpg file.&#xA;gpg --symmetric /tmp/keys/&amp;lt;NAME&amp;gt;.asc&#xA;&#xA;# To prevent having to trust all the same keys as before I&#39;ll export the trust database.&#xA;gpg --export-ownertrust &amp;gt; /tmp/keys/trustdb.txt &#xA;&#xA;# Lastly, I move the files to my external flash drive (USB).&#xA;mv /tmp/keys/&amp;lt;NAME&amp;gt;.asc.gpg /Volumes/.../&amp;lt;NAME&amp;gt;.asc.gpg&#xA;mv /tmp/keys/trustdb.txt /Volumes/.../trustdb.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next, I backup my SSH data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;# Recursively copy all files into a zip archive.&#xA;zip -r /tmp/keys/sshbackup ~/.ssh/&#xA;&#xA;# I list the contents of the zip archive to be sure I have everything in there.&#xA;unzip -l /tmp/keys/sshbackup.zip&#xA;&#xA;# Once archived I add a password to the file so people are unable to open it.&#xA;# This will produce a .zip.gpg file.&#xA;gpg --symmetric /tmp/keys/sshbackup.zip&#xA;&#xA;# Lastly, I move the file to my external flash drive (USB).&#xA;mv /tmp/keys/sshbackup.zip.gpg /Volumes/.../sshbackup.zip.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then I clear out the temporary directory:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;rm -rf /tmp/keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;steps&#34;&gt;Steps&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install Rust.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl --proto &#39;=https&#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install Go.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;https://go.dev/dl/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Import GPG/SSH keys.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir /tmp/keys&#xA;cd /tmp/keys&#xA;&#xA;gpg --decrypt /tmp/keys/&amp;lt;NAME&amp;gt;.gpg &amp;gt; &amp;lt;NAME&amp;gt;&#xA;gpg --import &amp;lt;NAME&amp;gt;.asc&#xA;&#xA;rm ~/.gnupg/trustdb.gpg&#xA;gpg --import-ownertrust &amp;lt; /tmp/keys/trustdb.txt&#xA;&#xA;gpg --decrypt /tmp/keys/sshbackup.zip.gpg &amp;gt; sshbackup.zip&#xA;unzip /tmp/keys/sshbackup.zip&#xA;mv /tmp/keys/.ssh/ ~/&#xA;&#xA;rm -rf /tmp/keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Setup SSH.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;eval &amp;quot;$(ssh-agent -s)&amp;quot;&#xA;ssh-add --apple-use-keychain ~/.ssh/github&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve since moved to &lt;a href=&#34;https://www.warp.dev/&#34; target=&#34;_blank&#34;&gt;https://www.warp.dev/&lt;/a&gt; (see my &lt;a href=&#34;/posts/dev-tools/&#34;&gt;Dev Tools post&lt;/a&gt;)&lt;br&gt;&#xA;so I no longer use Alacritty or Fig (steps 5 and 6 below).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install Alacritty.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# https://github.com/alacritty/alacritty/releases&#xA;mkdir .bash_completion&#xA;curl https://raw.githubusercontent.com/alacritty/alacritty/master/extra/completions/alacritty.bash \&#xA;    -o ~/.bash_completion/alacritty&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install Fig.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;https://fig.io/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install Homebrew + packages.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# https://brew.sh&#xA;brew bundle --file /tmp/Brewfile install&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Change default shell to Zsh.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo /opt/homebrew/bin/zsh | sudo tee -a /etc/shells&#xA;chsh -s /opt/homebrew/bin/zsh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve since moved to &lt;a href=&#34;https://neovim.io/&#34; target=&#34;_blank&#34;&gt;https://neovim.io/&lt;/a&gt; (see my &lt;a href=&#34;/posts/dev-tools/&#34;&gt;Dev Tools post&lt;/a&gt;)&lt;br&gt;&#xA;so I no longer use Vim-Plug (step 9 below).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Configure Vim-Plug.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sh -c &#39;curl -fLo &amp;quot;${XDG_DATA_HOME:-$HOME/.local/share}&amp;quot;/nvim/site/autoload/plug.vim --create-dirs \&#xA;     https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I no longer use tmux (see my &lt;a href=&#34;/posts/dev-tools/&#34;&gt;Dev Tools post&lt;/a&gt;)&lt;br&gt;&#xA;so a bunch of the following step 10 has changed.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Setup dotfiles.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Don&amp;rsquo;t forget to execute &amp;lsquo;prefix + I&amp;rsquo; in tmux to install plugins.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cd /tmp&#xA;git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm&#xA;git clone https://github.com/Integralist/dotfiles.git&#xA;curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -o ~/.git-prompt.sh&#xA;curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh -o ~/.zsh/_git&#xA;cp -R .alacritty.yml .zsh .zshrc .config .gitconfig .gitignore .gnupg .ignore .inputrc .leptonrc .tmux.conf ~/&#xA;chown -R $(whoami) ~/.gnupg/&#xA;chmod 600 ~/.gnupg/*&#xA;chmod 700 ~/.gnupg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Setup password store.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;KEY_ID=$(gpg --list-keys &amp;lt;NAME&amp;gt; | head -n 2 | tail -n 1 | cut -d &#39; &#39; -f 7)&#xA;pass init $KEY_ID&#xA;pass git init&#xA;pass git remote add origin git@github.com:&amp;lt;private/repo&amp;gt;&#xA;pass git pull&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I no longer use Safari (see my &lt;a href=&#34;/posts/dev-tools/&#34;&gt;Dev Tools post&lt;/a&gt;)&lt;br&gt;&#xA;so step 12 is redundant now.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Safari extensions.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;AdBlock One&#xA;Dark Reader for Safari&#xA;Super Agent for Safari (Cookie Consent Automation)&#xA;Tab Sessions&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Configure OS.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;- Dock (Automatically hide and show the Dock)&#xA;- Keyboard (Key Repeat = Fast, Delay Until Repeat = Short)&#xA;- Accessibility &amp;gt; Zoom (Use keyboard shortcuts to zoom)&#xA;- Date &amp;amp; Time &amp;gt; Clock (Show date + Display the time with seconds)&#xA;- Mission Control (disable &amp;quot;Automatically rearrange Spaces based on most recent use&amp;quot;)&#xA;- Terminal Developer Mode (`spctl developer-mode enable-terminal`)&#xA;- Wake up from sleep (`sudo pmset -a standbydelay 7200`)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/laptop-setup-v2/</guid>
      <link>https://www.integralist.co.uk/posts/laptop-setup-v2/</link>
      <pubDate>Thu, 26 May 2022 00:00:00 +0000</pubDate>
      <title>New Laptop Configuration (Second Edition)</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;installing-go&#34;&gt;Installing Go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;All versions of Go are available to download here: &lt;a href=&#34;https://go.dev/dl/&#34; target=&#34;_blank&#34;&gt;https://go.dev/dl/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The installation directory will be: &lt;code&gt;/usr/local/go&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have Go installed, you can then use the &lt;code&gt;go&lt;/code&gt; command to either install go based tools/binaries or other versions of Go.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Additionally, you can automate the install via a terminal using the following shell function (only tested on macOS):&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# you can swap `ag` for `grep` if you prefer&#xA;alias golatest=&amp;quot;curl -L https://github.com/golang/go/tags 2&amp;gt;&amp;amp;1 |\&#xA;ag &#39;/golang/go/releases/tag/go[\w.]+&#39; -o | cut -d &#39;/&#39; -f 6 | awk NR==1 | ag &#39;\d.+&#39; -o&amp;quot;&#xA;&#xA;function go_install {&#xA;  if [ -z &amp;quot;$1&amp;quot; ]; then&#xA;    echo USAGE: go_install 1.18.1 OR go_install \$\(golatest\)&#xA;    return&#xA;  fi&#xA;  v=$1&#xA;  osname=$(uname -s | tr &#39;[:upper:]&#39; &#39;[:lower:]&#39;)&#xA;  hardware=$(uname -m)&#xA;  mkdir -p ~/goversions&#xA;  if ! test -f &amp;quot;~/goversions/go$v.$osname-$hardware.pkg&amp;quot;; then&#xA;    printf &amp;quot;\nDownloading %s\n\n&amp;quot; &amp;quot;go$v.$osname-$hardware&amp;quot;&#xA;    curl -L -o ~/goversions/go$v.$osname-$hardware.pkg https://go.dev/dl/go$v.$osname-$hardware.pkg&#xA;  fi&#xA;  echo &amp;quot;&amp;quot;&#xA;  sudo rm -rf /usr/local/go; sudo installer -pkg ~/goversions/go$v.$osname-$hardware.pkg -target /usr/local/&#xA;  clear&#xA;  go version&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;installing-binaries&#34;&gt;Installing binaries&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of version go 1.16 &lt;code&gt;go install&lt;/code&gt; is now responsible only for installing binaries, &lt;em&gt;not&lt;/em&gt; modifying a &lt;code&gt;go.mod&lt;/code&gt; file (that&amp;rsquo;s what &lt;code&gt;go get&lt;/code&gt; is for).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go install example.com/cmd@v1.0.0&#xA;go install example.com/cmd@latest&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;See &lt;a href=&#34;https://go.dev/ref/mod#go-install&#34; target=&#34;_blank&#34;&gt;reference documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;installing-different-go-versions&#34;&gt;Installing different go versions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following is the &amp;lsquo;official&amp;rsquo; approach&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;See &lt;a href=&#34;https://go.dev/doc/manage-install#installing-multiple&#34; target=&#34;_blank&#34;&gt;reference documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go install golang.org/dl/go1.18@latest&#xA;go1.18 download&#xA;go1.18 version # go version go1.18 darwin/amd64&#xA;alias go=go1.18&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want a simple binary overwrite of the global &lt;code&gt;go&lt;/code&gt; command (for example, an &lt;code&gt;alias&lt;/code&gt; doesn&amp;rsquo;t work with Makefiles that reference &lt;code&gt;go&lt;/code&gt; because make targets run in a subshell):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go install golang.org/dl/go1.18@latest&#xA;go1.18 download&#xA;sudo cp $(which go1.18) $(which go)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;This requires &lt;code&gt;sudo&lt;/code&gt; as it&amp;rsquo;s copying into &lt;code&gt;/usr/local/...&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you want the latest &amp;lsquo;tip&amp;rsquo; release (and maybe with additional/unreleased features, at the time of writing that might have included something like &amp;lsquo;fuzzing&amp;rsquo; which was made available in &lt;code&gt;go1.18&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go install golang.org/dl/gotip&#xA;gotip download dev.fuzz # also download a dev/tip specific tool/feature&#xA;gotip test -fuzz=FuzzFoo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;basic-switcher-using-go-mod-as-reference&#34;&gt;Basic switcher using &lt;code&gt;go.mod&lt;/code&gt; as reference&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# This function identifies the go version specified in a project&#39;s go.mod&#xA;# It then attempts to switch to a binary of that version.&#xA;# If none exists it will instruct you how to download it.&#xA;#&#xA;# NOTE: Some tools, e.g. TinyGo, won&#39;t work with this approach because we&#39;re&#xA;# just replacing the go binary and the VERSION file, where the originally&#xA;# installed version of go will have things like CGO files that TinyGo will try&#xA;# to use and if those don&#39;t align with the version of the binary we&#39;ve switched&#xA;# to, then it means TinyGo will fail to compile. &#xA;#&#xA;# In that scenario you&#39;re better off using the `go_install` shell function &#xA;# approach at the top of the page.&#xA;function go_version {&#xA;    if [ -f &amp;quot;go.mod&amp;quot; ]; then&#xA;        v=$(grep -E &#39;^go \d.+$&#39; ./go.mod | grep -oE &#39;\d.+$&#39;)&#xA;        if [[ ! $(go version | grep &amp;quot;go$v&amp;quot;) ]]; then&#xA;          echo &amp;quot;&amp;quot;&#xA;          echo &amp;quot;About to switch go version to: $v&amp;quot;&#xA;          if ! command -v &amp;quot;$HOME/go/bin/go$v&amp;quot; &amp;amp;&amp;gt; /dev/null&#xA;          then&#xA;            echo &amp;quot;run: go install golang.org/dl/go$v@latest &amp;amp;&amp;amp; go$v download &amp;amp;&amp;amp; sudo cp \$(which go$v) \$(which go)&amp;quot;&#xA;            return&#xA;          fi&#xA;          sudo cp $(which go$v) $(which go)&#xA;          echo -n go$v | sudo tee $(dirname $(dirname $(which go)))/VERSION &amp;gt; /dev/null&#xA;        fi&#xA;    fi&#xA;}&#xA;&#xA;# To support the configuring our go environment we will override the cd&#xA;# command to call the go logic for checking the go version.&#xA;#&#xA;# NOTE: We use `command` and not `builtin` because the latter doesn&#39;t take into&#xA;# account anything available on the user&#39;s $PATH but also because it didn&#39;t&#xA;# work with the Starship prompt which seems to override cd also.&#xA;function cd {&#xA;  command cd &amp;quot;$@&amp;quot;&#xA;  RET=$?&#xA;  go_version&#xA;  return $RET&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;unofficial-goenv&#34;&gt;Unofficial: goenv&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/syndbg/goenv&#34; target=&#34;_blank&#34;&gt;https://github.com/syndbg/goenv&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The nice thing about goenv is that it lets you more easily automate a switch between projects using either &lt;code&gt;GOENV_VERSION&lt;/code&gt; or &lt;code&gt;.go-version&lt;/code&gt; (&lt;a href=&#34;https://github.com/syndbg/goenv/blob/master/HOW_IT_WORKS.md#choosing-the-go-version&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-install/</guid>
      <link>https://www.integralist.co.uk/posts/go-install/</link>
      <pubDate>Fri, 22 Apr 2022 00:00:00 +0000</pubDate>
      <title>Manage multiple versions of the Go programming language</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;update-november-2022&#34;&gt;UPDATE November 2022&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not long after I wrote this post I had switched from VimScript to using Lua and also making large sets of changes and tweaks to my configuration. The source of truth is:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/integralist/nvim&#34; target=&#34;_blank&#34;&gt;https://github.com/integralist/nvim&lt;/a&gt; (which is a submodule within &lt;a href=&#34;https://github.com/integralist/dotfiles&#34; target=&#34;_blank&#34;&gt;https://github.com/integralist/dotfiles&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post is being kept for posterity, but ultimately I would recommend you look at the above dotfiles repo instead.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;This is going to be a very focused post because when you&amp;rsquo;re looking to get your code editor configured you typically just want answers. Let&amp;rsquo;s go&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I configure Neovim with &lt;code&gt;~/.config/nvim/init.vim&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Executables.&lt;/li&gt;&#xA;&lt;li&gt;Plugin manager.&lt;/li&gt;&#xA;&lt;li&gt;An LSP (Language Server Protocol) client.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;executables&#34;&gt;Executables&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s a bunch of Rust and Go based tools we&amp;rsquo;ll want to have installed first.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Add the following to your &lt;code&gt;.bashrc&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export PATH=&amp;quot;/usr/local/go/bin:$PATH&amp;quot;&#xA;export PATH=&amp;quot;$HOME/go/bin:$PATH&amp;quot;&#xA;export PATH=&amp;quot;$HOME/.cargo/bin:$PATH&amp;quot;&#xA;&#xA;# rustup&#xA;#&#xA;# avoid https://github.com/rust-analyzer/rust-analyzer/issues/4172&#xA;#&#xA;# NOTE: Has to be defined after PATH update to locate .cargo directory.&#xA;#&#xA;export RUST_SRC_PATH=&amp;quot;$(rustc --print sysroot)/lib/rustlib/src/rust/src&amp;quot;&#xA;&#xA;# To support the configuring our go environment we will override the cd&#xA;# command to call the go logic for checking the go version.&#xA;#&#xA;# We also make sure to call ls when changing directories as it&#39;s nice to see&#xA;# what&#39;s in each directory.&#xA;#&#xA;# NOTE: We use `command` and not `builtin` because the latter doesn&#39;t take into&#xA;# account anything available on the user&#39;s $PATH but also because it didn&#39;t&#xA;# work with the Starship prompt which seems to override cd also.&#xA;function cd {&#xA;  command cd &amp;quot;$@&amp;quot;&#xA;  RET=$?&#xA;  ls&#xA;  go_version&#xA;  return $RET&#xA;}&#xA;&#xA;# configure go environment&#xA;#&#xA;# Custom go binaries are installed in $HOME/go/bin.&#xA;#&#xA;function go_version {&#xA;    if [ -f &amp;quot;go.mod&amp;quot; ]; then&#xA;        v=$(grep -E &#39;^go \d.+$&#39; ./go.mod | grep -oE &#39;\d.+$&#39;)&#xA;        if [[ ! $(go version | grep &amp;quot;go$v&amp;quot;) ]]; then&#xA;          echo &amp;quot;&amp;quot;&#xA;          echo &amp;quot;About to switch go version to: $v&amp;quot;&#xA;          if ! command -v &amp;quot;$HOME/go/bin/go$v&amp;quot; &amp;amp;&amp;gt; /dev/null&#xA;          then&#xA;            echo &amp;quot;run: go install golang.org/dl/go$v@latest &amp;amp;&amp;amp; go$v download &amp;amp;&amp;amp; \&#xA;              sudo cp \$(which go$v) \$(which go)&amp;quot;&#xA;            return&#xA;          fi&#xA;          sudo cp $(which go$v) $(which go)&#xA;        fi&#xA;    fi&#xA;}&#xA;if [ ! -f &amp;quot;$HOME/go/bin/gofumpt&amp;quot; ]; then&#xA;    go install mvdan.cc/gofumpt@latest&#xA;fi&#xA;if [ ! -f &amp;quot;$HOME/go/bin/revive&amp;quot; ]; then&#xA;    go install github.com/mgechev/revive@latest&#xA;fi&#xA;&#xA;# configure rust environment&#xA;#&#xA;# - autocomplete&#xA;# - rust-analyzer&#xA;# - cargo audit&#xA;# - cargo-nextest&#xA;# - cargo fmt&#xA;# - cargo clippy&#xA;# - cargo edit&#xA;#&#xA;source $HOME/.cargo/env&#xA;if [ ! -f &amp;quot;$HOME/.config/rustlang/autocomplete/rustup&amp;quot; ]; then&#xA;  mkdir -p ~/.config/rustlang/autocomplete&#xA;  rustup completions bash rustup &amp;gt;&amp;gt; ~/.config/rustlang/autocomplete/rustup&#xA;fi&#xA;source &amp;quot;$HOME/.config/rustlang/autocomplete/rustup&amp;quot;&#xA;if ! command -v rust-analyzer &amp;amp;&amp;gt; /dev/null&#xA;then&#xA;  brew install rust-analyzer&#xA;fi&#xA;if ! cargo audit --version &amp;amp;&amp;gt; /dev/null; then&#xA;  cargo install cargo-audit --features=fix&#xA;fi&#xA;if ! cargo nextest --version &amp;amp;&amp;gt; /dev/null; then&#xA;  cargo install cargo-nextest&#xA;fi&#xA;if ! cargo fmt --version &amp;amp;&amp;gt; /dev/null; then&#xA;  rustup component add rustfmt&#xA;fi&#xA;if ! cargo clippy --version &amp;amp;&amp;gt; /dev/null; then&#xA;  rustup component add clippy&#xA;fi&#xA;if ! ls ~/.cargo/bin | grep &#39;cargo-upgrade&#39; &amp;amp;&amp;gt; /dev/null; then&#xA;  cargo install cargo-edit&#xA;fi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;plugin-manager&#34;&gt;Plugin manager&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://github.com/junegunn/vim-plug&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;vim-plug&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;call plug#begin()&#xA;&#xA;Plug &#39;folke/trouble.nvim&#39;&#xA;Plug &#39;hrsh7th/cmp-buffer&#39;&#xA;Plug &#39;hrsh7th/cmp-nvim-lsp&#39;&#xA;Plug &#39;hrsh7th/cmp-nvim-lsp-signature-help&#39;&#xA;Plug &#39;hrsh7th/cmp-path&#39;&#xA;Plug &#39;hrsh7th/cmp-vsnip&#39;&#xA;Plug &#39;hrsh7th/nvim-cmp&#39;&#xA;Plug &#39;hrsh7th/vim-vsnip&#39;&#xA;Plug &#39;hrsh7th/vim-vsnip-integ&#39;&#xA;Plug &#39;j-hui/fidget.nvim&#39;&#xA;Plug &#39;kosayoda/nvim-lightbulb&#39;&#xA;Plug &#39;m-demare/hlargs.nvim&#39;&#xA;Plug &#39;neovim/nvim-lspconfig&#39;&#xA;Plug &#39;nvim-treesitter/nvim-treesitter&#39;, {&#39;do&#39;: &#39;:TSUpdate&#39;}&#xA;Plug &#39;simrat39/rust-tools.nvim&#39;&#xA;Plug &#39;weilbith/nvim-code-action-menu&#39;&#xA;Plug &#39;williamboman/nvim-lsp-installer&#39;&#xA;&#xA;call plug#end()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Define the above and run &lt;code&gt;:PlugInstall&lt;/code&gt;. Once everything is installed, continue to the next section.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;lsp&#34;&gt;LSP&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I use Neovim&amp;rsquo;s built-in LSP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Add the following plugin configuration:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;&amp;quot; ------------------------------------&#xA;&amp;quot; j-hui/fidget.nvim&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot;&#xA;lua require(&amp;quot;fidget&amp;quot;).setup()&#xA;&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot; kosayoda/nvim-lightbulb&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot;&#xA;autocmd CursorHold,CursorHoldI * lua require(&#39;nvim-lightbulb&#39;).update_lightbulb()&#xA;&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot; weilbith/nvim-code-action-menu&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot;&#xA;let g:code_action_menu_window_border = &#39;single&#39;&#xA;&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot; folke/trouble.nvim&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot;&#xA;lua require(&amp;quot;trouble&amp;quot;).setup()&#xA;&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot; Neovim LSP&#xA;&amp;quot; ------------------------------------&#xA;&amp;quot;&#xA;&amp;quot; Configure Rust LSP.&#xA;&amp;quot;&#xA;&amp;quot; https://github.com/simrat39/rust-tools.nvim#configuration&#xA;&amp;quot;&#xA;lua &amp;lt;&amp;lt;EOF&#xA;local opts = {&#xA;  -- rust-tools options&#xA;  tools = {&#xA;    autoSetHints = true,&#xA;    hover_with_actions = true,&#xA;    inlay_hints = {&#xA;      show_parameter_hints = true,&#xA;      parameter_hints_prefix = &amp;quot;&amp;quot;,&#xA;      other_hints_prefix = &amp;quot;&amp;quot;,&#xA;      },&#xA;    },&#xA;&#xA;  -- all the opts to send to nvim-lspconfig&#xA;  -- these override the defaults set by rust-tools.nvim&#xA;  -- https://github.com/rust-analyzer/rust-analyzer/blob/master\&#xA;     /docs/user/generated_config.adoc&#xA;  -- https://rust-analyzer.github.io/manual.html#features&#xA;  server = {&#xA;    settings = {&#xA;      [&amp;quot;rust-analyzer&amp;quot;] = {&#xA;        assist = {&#xA;          importEnforceGranularity = true,&#xA;          importPrefix = &amp;quot;crate&amp;quot;&#xA;          },&#xA;        cargo = {&#xA;          allFeatures = true&#xA;          },&#xA;        checkOnSave = {&#xA;          -- default: `cargo check`&#xA;          command = &amp;quot;clippy&amp;quot;&#xA;          },&#xA;        },&#xA;        inlayHints = {&#xA;          lifetimeElisionHints = {&#xA;            enable = true,&#xA;            useParameterNames = true&#xA;          },&#xA;        },&#xA;      }&#xA;    },&#xA;}&#xA;require(&#39;rust-tools&#39;).setup(opts)&#xA;EOF&#xA;&#xA;&amp;quot; Configure Golang LSP.&#xA;&amp;quot;&#xA;&amp;quot; https://github.com/golang/tools/blob/master/gopls/doc/settings.md&#xA;&amp;quot; https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md&#xA;&amp;quot; https://github.com/golang/tools/blob/master/gopls/doc/vim.md#neovim&#xA;&amp;quot; https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#gopls&#xA;&amp;quot; https://github.com/golang/tools/blob/master/gopls/doc/vim.md#neovim&#xA;&amp;quot; https://www.getman.io/posts/programming-go-in-neovim/&#xA;&amp;quot;&#xA;lua &amp;lt;&amp;lt;EOF&#xA;require(&#39;lspconfig&#39;).gopls.setup{&#xA;    cmd = {&#39;gopls&#39;},&#xA;  settings = {&#xA;    gopls = {&#xA;      analyses = {&#xA;        nilness = true,&#xA;        unusedparams = true,&#xA;        unusedwrite = true,&#xA;        useany = true,&#xA;      },&#xA;      experimentalPostfixCompletions = true,&#xA;      gofumpt = true,&#xA;      staticcheck = true,&#xA;      usePlaceholders = true,&#xA;    },&#xA;  },&#xA;    on_attach = on_attach,&#xA;}&#xA;EOF&#xA;&#xA;&amp;quot; Configure Golang Environment.&#xA;&amp;quot;&#xA;fun! GoFumpt()&#xA;  :silent !gofumpt -w %&#xA;  :edit&#xA;endfun&#xA;autocmd FileType go map &amp;lt;buffer&amp;gt; &amp;lt;leader&amp;gt;p :call \&#xA;  append(&amp;quot;.&amp;quot;, &amp;quot;fmt.Printf(\&amp;quot;%+v\\n\&amp;quot;, )&amp;quot;)&amp;lt;CR&amp;gt; &amp;lt;bar&amp;gt; :norm $a&amp;lt;CR&amp;gt;&amp;lt;esc&amp;gt;j==$i&#xA;autocmd FileType go map &amp;lt;buffer&amp;gt; &amp;lt;leader&amp;gt;e :call \&#xA;  append(&amp;quot;.&amp;quot;, &amp;quot;if err != nil {return err}&amp;quot;)&amp;lt;CR&amp;gt; &amp;lt;bar&amp;gt; :w&amp;lt;CR&amp;gt;&#xA;autocmd BufWritePost *.go call GoFumpt()&#xA;autocmd BufWritePost *.go :cex system(&#39;revive &#39;..expand(&#39;%:p&#39;)) | cwindow&#xA;&#xA;&amp;quot; Order imports on save, like goimports does:&#xA;&amp;quot;&#xA;lua &amp;lt;&amp;lt;EOF&#xA;  function OrgImports(wait_ms)&#xA;    local params = vim.lsp.util.make_range_params()&#xA;    params.context = {only = {&amp;quot;source.organizeImports&amp;quot;}}&#xA;    local result = vim.lsp.buf_request_sync(0, &amp;quot;textDocument/codeAction&amp;quot;, params, wait_ms)&#xA;    for _, res in pairs(result or {}) do&#xA;      for _, r in pairs(res.result or {}) do&#xA;        if r.edit then&#xA;          vim.lsp.util.apply_workspace_edit(r.edit, &amp;quot;UTF-8&amp;quot;)&#xA;        else&#xA;          vim.lsp.buf.execute_command(r.command)&#xA;        end&#xA;      end&#xA;    end&#xA;  end&#xA;EOF&#xA;autocmd BufWritePre *.go lua OrgImports(1000)&#xA;&#xA;&amp;quot; Configure LSP code navigation shortcuts&#xA;&amp;quot; as found in :help lsp&#xA;&amp;quot;&#xA;nnoremap &amp;lt;silent&amp;gt; &amp;lt;c-]&amp;gt;     &amp;lt;cmd&amp;gt;lua vim.lsp.buf.definition()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; &amp;lt;c-k&amp;gt;     &amp;lt;cmd&amp;gt;lua vim.lsp.buf.signature_help()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; K         &amp;lt;cmd&amp;gt;lua vim.lsp.buf.hover()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gi        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.implementation()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gc        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.incoming_calls()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gd        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.type_definition()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gr        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.references()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gn        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.rename()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gs        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.document_symbol()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; gw        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.workspace_symbol()&amp;lt;CR&amp;gt;&#xA;&#xA;&amp;quot; Replaced LSP implementation with code action plugin...&#xA;&amp;quot;&#xA;&amp;quot; nnoremap &amp;lt;silent&amp;gt; ga        &amp;lt;cmd&amp;gt;lua vim.lsp.buf.code_action()&amp;lt;CR&amp;gt;&#xA;&amp;quot;&#xA;nnoremap &amp;lt;silent&amp;gt; ga        &amp;lt;cmd&amp;gt;CodeActionMenu&amp;lt;CR&amp;gt;&#xA;&#xA;nnoremap &amp;lt;silent&amp;gt; [x        &amp;lt;cmd&amp;gt;lua vim.diagnostic.goto_prev()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; ]x        &amp;lt;cmd&amp;gt;lua vim.diagnostic.goto_next()&amp;lt;CR&amp;gt;&#xA;nnoremap &amp;lt;silent&amp;gt; ]s        &amp;lt;cmd&amp;gt;lua vim.diagnostic.show()&amp;lt;CR&amp;gt;&#xA;&#xA;&amp;quot; Replaced LSP implementation with trouble plugin...&#xA;&amp;quot;&#xA;&amp;quot; nnoremap &amp;lt;silent&amp;gt; &amp;lt;space&amp;gt;q  &amp;lt;cmd&amp;gt;lua vim.diagnostic.setloclist()&amp;lt;CR&amp;gt;&#xA;&amp;quot;&#xA;nnoremap &amp;lt;silent&amp;gt; &amp;lt;space&amp;gt;q  &amp;lt;cmd&amp;gt;Trouble&amp;lt;CR&amp;gt;&#xA;&#xA;&amp;quot; Setup Completion&#xA;&amp;quot; https://github.com/hrsh7th/nvim-cmp#recommended-configuration&#xA;&amp;quot;&#xA;lua &amp;lt;&amp;lt;EOF&#xA;local cmp = require(&#39;cmp&#39;)&#xA;cmp.setup({&#xA;  snippet = {&#xA;    expand = function(args)&#xA;        vim.fn[&amp;quot;vsnip#anonymous&amp;quot;](args.body)&#xA;    end,&#xA;  },&#xA;  mapping = {&#xA;    [&#39;&amp;lt;C-p&amp;gt;&#39;] = cmp.mapping.select_prev_item(),&#xA;    [&#39;&amp;lt;C-n&amp;gt;&#39;] = cmp.mapping.select_next_item(),&#xA;    [&#39;&amp;lt;S-Tab&amp;gt;&#39;] = cmp.mapping.select_prev_item(),&#xA;    [&#39;&amp;lt;Tab&amp;gt;&#39;] = cmp.mapping.select_next_item(),&#xA;    [&#39;&amp;lt;C-d&amp;gt;&#39;] = cmp.mapping.scroll_docs(-4),&#xA;    [&#39;&amp;lt;C-f&amp;gt;&#39;] = cmp.mapping.scroll_docs(4),&#xA;    [&#39;&amp;lt;C-Space&amp;gt;&#39;] = cmp.mapping(cmp.mapping.complete(), { &#39;i&#39;, &#39;c&#39; }),&#xA;    [&#39;&amp;lt;C-e&amp;gt;&#39;] = cmp.mapping.close(),&#xA;    [&#39;&amp;lt;CR&amp;gt;&#39;] = cmp.mapping.confirm({&#xA;      behavior = cmp.ConfirmBehavior.Insert,&#xA;      select = true,&#xA;    })&#xA;  },&#xA;  sources = {&#xA;    { name = &#39;nvim_lsp&#39; },&#xA;    { name = &#39;vsnip&#39; },&#xA;    { name = &#39;path&#39; },&#xA;    { name = &#39;buffer&#39; },&#xA;    { name = &#39;nvim_lsp_signature_help&#39; },&#xA;  },&#xA;})&#xA;EOF&#xA;&#xA;&amp;quot; Setup Treesitter and friends&#xA;&amp;quot;&#xA;&amp;quot; NOTE: originally used `ensure_installed = &amp;quot;all&amp;quot;` but an experimental PHP&#xA;&amp;quot; parser was causing NPM lockfile errors.&#xA;&amp;quot;&#xA;lua &amp;lt;&amp;lt;EOF&#xA;require(&#39;nvim-treesitter.configs&#39;).setup {&#xA;  ensure_installed = { &#xA;    &amp;quot;bash&amp;quot;, &#xA;    &amp;quot;c&amp;quot;, &#xA;    &amp;quot;cmake&amp;quot;, &#xA;    &amp;quot;css&amp;quot;, &#xA;    &amp;quot;dockerfile&amp;quot;, &#xA;    &amp;quot;go&amp;quot;, &#xA;    &amp;quot;gomod&amp;quot;, &#xA;    &amp;quot;gowork&amp;quot;, &#xA;    &amp;quot;hcl&amp;quot;, &#xA;    &amp;quot;help&amp;quot;, &#xA;    &amp;quot;html&amp;quot;, &#xA;    &amp;quot;http&amp;quot;, &#xA;    &amp;quot;javascript&amp;quot;, &#xA;    &amp;quot;json&amp;quot;, &#xA;    &amp;quot;lua&amp;quot;, &#xA;    &amp;quot;make&amp;quot;, &#xA;    &amp;quot;markdown&amp;quot;, &#xA;    &amp;quot;python&amp;quot;, &#xA;    &amp;quot;regex&amp;quot;, &#xA;    &amp;quot;ruby&amp;quot;, &#xA;    &amp;quot;rust&amp;quot;, &#xA;    &amp;quot;toml&amp;quot;, &#xA;    &amp;quot;vim&amp;quot;, &#xA;    &amp;quot;yaml&amp;quot;, &#xA;    &amp;quot;zig&amp;quot;&#xA;  },&#xA;  highlight = {&#xA;    enable = true,&#xA;  },&#xA;  rainbow = {&#xA;    enable = true,&#xA;    extended_mode = true,&#xA;    max_file_lines = nil,&#xA;  }&#xA;}&#xA;require(&#39;hlargs&#39;).setup()&#xA;EOF&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/neovim-rust-go/</guid>
      <link>https://www.integralist.co.uk/posts/neovim-rust-go/</link>
      <pubDate>Thu, 14 Apr 2022 00:00:00 +0000</pubDate>
      <title>Setting up Neovim for Rust and Go development</title>
    </item>
    <item>
      <description>&lt;p&gt;I&amp;rsquo;ve been around the houses on this problem long enough, and after many years of trying various tricks and having them fail I decided to document an actual working solution.&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Install a terminal that has good colour support (e.g. &lt;a href=&#34;https://alacritty.org/&#34; target=&#34;_blank&#34;&gt;Alacritty&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Install a better Vim (i.e. &lt;a href=&#34;https://neovim.io&#34; target=&#34;_blank&#34;&gt;Neovim&lt;/a&gt;) †&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† This should still work with standard Vim, but actually Neovim has so many performance improvements, and quality of life plugins it&amp;rsquo;s not worth fighting for purity (trust me, I had been using standard vim and the standard macOS terminal app for 10 years before admitting I was fighting the tide).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now that you have the right tools, let&amp;rsquo;s explain the configuration.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;~/.config/nvim/init.vim&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;&amp;quot; this will tell Neovim to enable 24bit true color&#xA;if (has(&amp;quot;termguicolors&amp;quot;))&#xA; set termguicolors&#xA;endif&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;~/.bashrc&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# this isn&#39;t necessary when using Neovim in an appropriate terminal, &#xA;# but it will help when running Neovim inside of tmux.&#xA;export TERM=&amp;quot;xterm-256color&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;~/.tmux.conf&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;set-option -g default-terminal &#39;screen-256color-bce&#39;&#xA;set-option -ga terminal-overrides &amp;quot;,xterm-256color:Tc&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The tmux manual states that &lt;code&gt;default-terminal&lt;/code&gt; should be set to &lt;code&gt;screen&lt;/code&gt;, &lt;code&gt;tmux&lt;/code&gt; or a derivative of them, which is why this doesn&amp;rsquo;t get set to the same value (&lt;code&gt;xterm-256color&lt;/code&gt;) that &lt;code&gt;TERM&lt;/code&gt; has in the &lt;code&gt;.bashrc&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, we use the &lt;code&gt;-bce&lt;/code&gt; suffix (rather than just setting &lt;code&gt;screen-256color&lt;/code&gt;) because otherwise tmux won&amp;rsquo;t use a transparent background. Having a transparent background allows the terminal colour palette to be utilised and this helps Vim themes to display correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, &lt;code&gt;terminal-overrides&lt;/code&gt; let&amp;rsquo;s you configure tmux to know about terminal capabilities it otherwise might not be able to detect by itself. So this is why we set it to the same value (&lt;code&gt;xterm-256color&lt;/code&gt;) that &lt;code&gt;TERM&lt;/code&gt; has in the &lt;code&gt;.bashrc&lt;/code&gt; file.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/vim-themes/</guid>
      <link>https://www.integralist.co.uk/posts/vim-themes/</link>
      <pubDate>Thu, 14 Apr 2022 00:00:00 +0000</pubDate>
      <title>Fix broken Vim Themes</title>
    </item>
    <item>
      <description>&lt;p&gt;I don&amp;rsquo;t know who needs to hear this but:&lt;br&gt;&#xA;&lt;strong&gt;I love my developer tools&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;core&#34;&gt;Core&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Package Manager&lt;/strong&gt;: &lt;a href=&#34;https://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Terminal&lt;/strong&gt;: &lt;a href=&#34;https://ghostty.org&#34; target=&#34;_blank&#34;&gt;Ghostty&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Code Editor&lt;/strong&gt;: &lt;a href=&#34;https://neovim.io&#34; target=&#34;_blank&#34;&gt;Neovim&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;history&#34;&gt;History&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Used stock macOS Terminal.app with &lt;a href=&#34;https://github.com/tmux/tmux/wiki&#34; target=&#34;_blank&#34;&gt;tmux&lt;/a&gt;&#xA;for 10+ years.&lt;/li&gt;&#xA;&lt;li&gt;I tried &lt;a href=&#34;https://iterm2.com/&#34; target=&#34;_blank&#34;&gt;iTerm2&lt;/a&gt;,&#xA;&lt;a href=&#34;https://sw.kovidgoyal.net/kitty/&#34; target=&#34;_blank&#34;&gt;Kitty&lt;/a&gt;, &lt;a href=&#34;https://alacritty.org/&#34; target=&#34;_blank&#34;&gt;Alacritty&lt;/a&gt;,&#xA;&lt;a href=&#34;https://wezfurlong.org/wezterm/&#34; target=&#34;_blank&#34;&gt;WesTerm&lt;/a&gt; but none really fit well for me.&lt;/li&gt;&#xA;&lt;li&gt;Constant colour issues forced me to switch from tmux to&#xA;&lt;a href=&#34;https://zellij.dev&#34; target=&#34;_blank&#34;&gt;Zellij&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;I moved to using &lt;a href=&#34;https://www.warp.dev/&#34; target=&#34;_blank&#34;&gt;Warp&lt;/a&gt; for a few years, but it still&#xA;had issues.&lt;/li&gt;&#xA;&lt;li&gt;I finally landed on &lt;a href=&#34;https://ghostty.org&#34; target=&#34;_blank&#34;&gt;Ghostty&lt;/a&gt; which has been great. Yes,&#xA;it still has minor issues but the community is active and open.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;workflow&#34;&gt;Workflow&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I use &lt;a href=&#34;https://www.zsh.org&#34; target=&#34;_blank&#34;&gt;Zsh&lt;/a&gt; Autocomplete with&#xA;&lt;a href=&#34;https://github.com/Aloxaf/fzf-tab&#34; target=&#34;_blank&#34;&gt;fzf-tab&lt;/a&gt; to replace Zsh&amp;rsquo;s default completion&#xA;selection menu with &lt;a href=&#34;https://github.com/junegunn/fzf&#34; target=&#34;_blank&#34;&gt;fzf&lt;/a&gt; which works really&#xA;nicely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I mostly use terminal splits and tabs for dividing up projects and tasks, and on&#xA;the occasion I&amp;rsquo;ll use Neovim&amp;rsquo;s built-in terminal across multiple splits or&#xA;floating windows. Otherwise, the other part of Ghostty I use &lt;em&gt;a lot&lt;/em&gt; is its&#xA;floating terminal that can be triggered from anywhere via a hotkey (as long as&#xA;Ghostty is open somewhere).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;💡 You can find my Neovim config &lt;a href=&#34;https://github.com/integralist/nvim&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; and&#xA;my dotfiles &lt;a href=&#34;https://github.com/integralist/dotfiles&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;supplementary&#34;&gt;Supplementary&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Code Statistics&lt;/strong&gt;: &lt;a href=&#34;https://github.com/XAMPPRocky/tokei/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Tokei&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;DNS Client&lt;/strong&gt;: &lt;a href=&#34;https://github.com/mr-karan/doggo/blob/main/README.md&#34; target=&#34;_blank&#34;&gt;Doggo&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Directory Lister&lt;/strong&gt;: &lt;a href=&#34;https://en.wikipedia.org/wiki/Tree_(command)&#34; target=&#34;_blank&#34;&gt;Tree&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Directory Navigator&lt;/strong&gt;: &lt;a href=&#34;https://github.com/Canop/broot/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Broot&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Directory Switcher&lt;/strong&gt;: &lt;a href=&#34;https://github.com/ajeetdsouza/zoxide/blob/main/README.md&#34; target=&#34;_blank&#34;&gt;Zoxide&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Disk Usage&lt;/strong&gt;: &lt;a href=&#34;https://github.com/muesli/duf/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Duf&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Feed Reader&lt;/strong&gt;: &lt;a href=&#34;https://github.com/veeso/tuifeed/blob/main/README.md&#34; target=&#34;_blank&#34;&gt;Tuifeed&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;File Content Display&lt;/strong&gt;: &lt;a href=&#34;https://github.com/sharkdp/bat/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Bat&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;File Finder&lt;/strong&gt;: &lt;a href=&#34;https://github.com/sharkdp/fd/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Fd&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;File Lister&lt;/strong&gt;: &lt;a href=&#34;https://github.com/ogham/exa/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Exa&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;File Removal&lt;/strong&gt;: &lt;a href=&#34;https://github.com/nivekuil/rip/blob/master/README.org&#34; target=&#34;_blank&#34;&gt;Rip&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;File Space Usage&lt;/strong&gt;: &lt;a href=&#34;https://github.com/bootandy/dust/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Dust&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Network Reachability&lt;/strong&gt;: &lt;a href=&#34;https://github.com/orf/gping/blob/master/readme.md&#34; target=&#34;_blank&#34;&gt;Gping&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Network Utilisation&lt;/strong&gt;: &lt;a href=&#34;https://github.com/imsnif/bandwhich/blob/main/README.md&#34; target=&#34;_blank&#34;&gt;Bandwhich&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Process Status&lt;/strong&gt;: &lt;a href=&#34;https://github.com/dalance/procs/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Procs&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Process/System Monitor&lt;/strong&gt;: &lt;a href=&#34;https://github.com/htop-dev/htop/#readme&#34; target=&#34;_blank&#34;&gt;Htop&lt;/a&gt; †&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shell&lt;/strong&gt;: &lt;a href=&#34;https://www.zsh.org&#34; target=&#34;_blank&#34;&gt;Zsh&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shell Autocomplete&lt;/strong&gt;: &lt;a href=&#34;https://github.com/Aloxaf/fzf-tab&#34; target=&#34;_blank&#34;&gt;FZF-tab&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shell Prompt&lt;/strong&gt;: &lt;a href=&#34;https://starship.rs/&#34; target=&#34;_blank&#34;&gt;Starship&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† I had switched to&#xA;&lt;a href=&#34;https://github.com/ClementTsang/bottom/blob/master/README.md&#34; target=&#34;_blank&#34;&gt;Bottom&lt;/a&gt; but&#xA;&lt;code&gt;htop&lt;/code&gt; is so much more flexible and configurable, and although the graphs in&#xA;&lt;code&gt;btm&lt;/code&gt; are nice, I don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; them.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;browser&#34;&gt;Browser&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Controversial, but I had moved away from&#xA;&lt;a href=&#34;https://www.mozilla.org/en-GB/firefox/new/&#34; target=&#34;_blank&#34;&gt;Firefox&lt;/a&gt; with a whole suite of&#xA;security/privacy minded tools to &lt;a href=&#34;https://www.apple.com/uk/safari/&#34; target=&#34;_blank&#34;&gt;Apple&amp;rsquo;s&#xA;Safari&lt;/a&gt; browser.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I &lt;em&gt;was&lt;/em&gt; using Safari&amp;rsquo;s &lt;a href=&#34;https://twitter.com/integralist/status/1514526555275501569?s=20&amp;amp;t=BJu3WlWq6dhoeAarJf91ig&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;Tab&#xA;Group&amp;rdquo;&lt;/a&gt;&#xA;feature, which I &lt;em&gt;really&lt;/em&gt; liked along with the following extensions&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;AdBlock One&lt;/li&gt;&#xA;&lt;li&gt;Dark Reader for Safari&lt;/li&gt;&#xA;&lt;li&gt;SimplyJSON for Safari&lt;/li&gt;&#xA;&lt;li&gt;Super Agent for Safari (Cookie Consent Automation)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;but ultimately the Tab Groups feature ended up being super buggy and&#xA;duplicating bookmarks and groups etc and I couldn&amp;rsquo;t get the issue resolved, so I&#xA;ended up back with Google Chrome.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;💡 In the future I&amp;rsquo;ll likely switch over to using&#xA;&lt;a href=&#34;https://ladybird.org/&#34; target=&#34;_blank&#34;&gt;Ladybird&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/dev-tools/</guid>
      <link>https://www.integralist.co.uk/posts/dev-tools/</link>
      <pubDate>Wed, 09 Mar 2022 00:00:00 +0000</pubDate>
      <title>Developer Tools</title>
    </item>
    <item>
      <description>&lt;p&gt;This is my own personal style guide for Go.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-materials&#34;&gt;Reference Materials&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following reference materials are my &amp;lsquo;go to&amp;rsquo; whenever I&amp;rsquo;m unsure of something (they&amp;rsquo;re mostly official resources).&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://go.dev/doc/modules/layout&#34; target=&#34;_blank&#34;&gt;Project structure&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://golang.org/doc/effective_go&#34; target=&#34;_blank&#34;&gt;Effective Go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/golang/go/wiki/CodeReviewComments&#34; target=&#34;_blank&#34;&gt;Code Review Comments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://talks.golang.org/2014/names.slide&#34; target=&#34;_blank&#34;&gt;What&amp;rsquo;s in a name?&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/golang/go/wiki/CommitMessage&#34; target=&#34;_blank&#34;&gt;Commit messages&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/golang/go/wiki/Comments&#34; target=&#34;_blank&#34;&gt;Comments&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://blogtitle.github.io/go-slices-gotchas/&#34; target=&#34;_blank&#34;&gt;Slice Gotchas&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;/posts/go-interfaces/&#34;&gt;Thinking about interfaces&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/22ced4b4700df1e6cbec88c1074c8b2d&#34; target=&#34;_blank&#34;&gt;Understanding memory allocation&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/05fb91c42021195b727be5afb28122ec&#34; target=&#34;_blank&#34;&gt;Go Concurrency&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Refer to the &lt;a href=&#34;https://golang.org/ref/spec&#34; target=&#34;_blank&#34;&gt;specification&lt;/a&gt; if ever confused about what the expected behaviour is.&lt;br&gt;&#xA;See also the &lt;a href=&#34;https://go.dev/doc/modules/gomod-ref&#34; target=&#34;_blank&#34;&gt;go.mod reference&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;naming&#34;&gt;Naming&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following is a summary of how to name things in Go, gleaned from either my own experiences over the years or from some of the above reference materials.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Choose package names that lend meaning to the names they export (see also &lt;a href=&#34;https://google.github.io/styleguide/go/&#34; target=&#34;_blank&#34;&gt;Google&amp;rsquo;s Go style guide&lt;/a&gt; for &lt;a href=&#34;https://google.github.io/styleguide/go/decisions.html#package-names&#34; target=&#34;_blank&#34;&gt;examples&lt;/a&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Where types are descriptive, name should be short (1 or 2 char name).&lt;/li&gt;&#xA;&lt;li&gt;If longer name required, consider refactoring into smaller functions.&lt;/li&gt;&#xA;&lt;li&gt;Commonly used names:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;i&lt;/code&gt; to &lt;code&gt;index&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;r&lt;/code&gt; to &lt;code&gt;reader&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;buf&lt;/code&gt; to &lt;code&gt;buffer&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;cfg&lt;/code&gt; to &lt;code&gt;config&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;dst, src&lt;/code&gt; to &lt;code&gt;destination, source&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;in, out&lt;/code&gt; when referring to stdin/stdout (more flexible for mocked objects).&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;rx, tx&lt;/code&gt; when dealing with channels.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;i.e. receiver, transmitter.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;data&lt;/code&gt; when referring to file content.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Regardless of it being a &lt;code&gt;string&lt;/code&gt; or &lt;code&gt;[]byte&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;ok&lt;/code&gt; instead of longer alternatives.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Errors:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Types: &lt;code&gt;&amp;lt;T&amp;gt;Error&lt;/code&gt; (e.g. &lt;code&gt;type ExitError struct {...}&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Values: &lt;code&gt;Err&amp;lt;T&amp;gt;&lt;/code&gt; (e.g. &lt;code&gt;var ErrFoo = errors.New(&amp;quot;bar: baz&amp;quot;)&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Interfaces:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When an interface includes multiple methods, choose a name that accurately describes its purpose.&lt;/li&gt;&#xA;&lt;li&gt;Interfaces defining one method are named the same as the method with &amp;lsquo;er&amp;rsquo; appended.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Sometimes the result isn&amp;rsquo;t correct English, that&amp;rsquo;s OK.&lt;/li&gt;&#xA;&lt;li&gt;Sometimes we use English to make it nicer.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Return values on exported functions should only be named for documentation purposes.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Side effect is that the variable is initialised at start of function with zero value.&lt;/li&gt;&#xA;&lt;li&gt;This can, in some cases, lead to a nice code design.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Set&amp;lt;T&amp;gt;&lt;/code&gt; vs &lt;code&gt;Register&amp;lt;T&amp;gt;&lt;/code&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Set&lt;/strong&gt;: use when flipping a bit (e.g. setting an int, string etc).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Register&lt;/strong&gt;: use when operation is going &lt;em&gt;into&lt;/em&gt; something (e.g. registering a CLI flag inside a command).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Tests:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Prefer &lt;code&gt;got, want&lt;/code&gt; over alternatives like &lt;code&gt;have, want&lt;/code&gt; (&lt;a href=&#34;https://github.com/golang/go/wiki/TestComments#got-before-want&#34; target=&#34;_blank&#34;&gt;official reference&lt;/a&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Refer also to &lt;a href=&#34;https://github.com/kettanaito/naming-cheatsheet&#34; target=&#34;_blank&#34;&gt;https://github.com/kettanaito/naming-cheatsheet&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;whitespace&#34;&gt;Whitespace&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The go standard library has no strong conventions or idioms for how to handle whitespace. So try and be concise without leaving the user with a wall of text to digest. Additionally, you can use block syntax &lt;code&gt;{...}&lt;/code&gt; to help group related logic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// Simple code is fine to condense the whitespace.&#xA;if ... {&#xA;  foo&#xA;  for x := range y {&#xA;    ...&#xA;  }&#xA;  bar&#xA;}&#xA;&#xA;// Complex code could benefit from some whitespace (also separate block syntax for grouping related logic).&#xA;if {&#xA;  ...&#xA;&#xA;  {&#xA;    ...grouping of related logic...&#xA;  }&#xA;&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-note-on-code-design&#34;&gt;Quick note on Code Design&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not always obvious but be wary of returning concrete types when building a package to be used as a library.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example of why this might be problematic: we had a library that defined a constructor that returned a struct of type &lt;code&gt;*T&lt;/code&gt;. This struct had methods attached and inside of those methods were API calls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason the returning of that struct was a problem was because when we built a separate CLI to consume the package library, we realised our CLI&amp;rsquo;s test suite wasn&amp;rsquo;t able to &lt;em&gt;mock&lt;/em&gt; the returned type appropriately as some of the fields on the struct were private (these would determine if an attached method would make an API call), and so we were forced to make real API calls!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution was for us to return an interface. This made it simple to mock the behaviours we wanted (e.g. we could write our tests to pretend there was an API error, and see how our CLI handled that scenario).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I recommend reading my other post &lt;a href=&#34;/posts/go-interfaces/&#34;&gt;&amp;ldquo;Thinking about Interfaces in Go&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-guide-to-errors&#34;&gt;Quick guide to Errors&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you wrap errors your message &lt;strong&gt;should include&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A pointer to where within your method the failure occurred.&lt;/li&gt;&#xA;&lt;li&gt;Values that will be useful during debugging (e.g ids).&lt;/li&gt;&#xA;&lt;li&gt;(sometimes) Details about why the error occurred.&lt;/li&gt;&#xA;&lt;li&gt;Other relevant info the caller doesn&amp;rsquo;t know.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;And your message &lt;strong&gt;should NOT include&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The name of your function&lt;/li&gt;&#xA;&lt;li&gt;Any of the arguments to your function&lt;/li&gt;&#xA;&lt;li&gt;Any other information that is already known to the caller&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here is a BAD example where the caller of a function that fails is seeing duplicate information:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// Source&#xA;func MightFail(id string) error {&#xA;    err := sqlStatement()&#xA;    if err != nil {&#xA;        return fmt.Errorf(&amp;quot;mightFail failed with id %v because of sql: %w&amp;quot;, id, err&#xA;    }&#xA;    ...&#xA;    return nil&#xA;}&#xA;&#xA;// Caller&#xA;func business(ids []string) error {&#xA;    for _, id := range ids {&#xA;        err := MightFail(id)&#xA;        if err != nil {&#xA;            return fmt.Errorf(&amp;quot;business failed MightFail on id %v: %w&amp;quot;, id, err)&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The resolution to the above bad code is: only include information the caller doesn’t have. The caller is free to annotate your errors with information such as the name of your function, arguments they passed in, etc. There is no need for you to provide that information to them, as its obvious up front. If this same logic is applied consistently you&amp;rsquo;ll end up with error messages that are high-signal and to-the-point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See also the article &amp;ldquo;&lt;a href=&#34;https://scribe.rip/when-life-gives-you-lemons-write-better-error-messages-46c5223e1a2f&#34; target=&#34;_blank&#34;&gt;When life gives you lemons, write better error messages&lt;/a&gt;&amp;rdquo;, from which the following images are sourced.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Bad error message&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/error-message-bad.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/error-message-bad.png&#34; alt=&#34;error message bad&#34; /&gt;&lt;/a&gt;&#xA;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Good error message&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/error-message-good.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/error-message-good.png&#34; alt=&#34;error message good&#34; /&gt;&lt;/a&gt;&#xA;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Essentially, the error &amp;ldquo;message&amp;rdquo; shouldn&amp;rsquo;t necessarily be formatted like &amp;ldquo;error doing x&amp;rdquo; or &amp;ldquo;failed to do x&amp;rdquo; (as I had been led to believe the former was the standard way of writing an error message). After reviewing &amp;ldquo;good&amp;rdquo; examples of Go code (e.g. at the time of writing &lt;a href=&#34;https://github.com/search?q=repo%3Agoogle%2Fexposure-notifications-server%20errors.New&amp;amp;type=code&#34; target=&#34;_blank&#34;&gt;this was one such example&lt;/a&gt;) it seems there is no &amp;lsquo;format&amp;rsquo; for the error message other than to be direct/specific.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-guide-to-panic&#34;&gt;Quick guide to &lt;code&gt;panic&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The use of &lt;code&gt;panic&lt;/code&gt; is reserved for when an error is &lt;em&gt;unrecoverable&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;What constitutes an &amp;ldquo;unrecoverable&amp;rdquo; error is contentious. Here are some definitions:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To indicate that something impossible has happened, such as exiting an infinite loop.&lt;/li&gt;&#xA;&lt;li&gt;During initialization, if the library truly cannot set itself up, it might be reasonable to &lt;code&gt;panic&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;When something internally has fundamentally failed.&lt;/li&gt;&#xA;&lt;li&gt;When a programmer gives something to a function which the function explicitly states is invalid.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/golang/go/blob/8ac6544/src/bytes/buffer.go#L88-L90&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;bytes.Truncate&lt;/code&gt;&lt;/a&gt; is an example of the last sub-point.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The above example could be considered &lt;em&gt;aggressive&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Instead the standard library could have returned an error so the caller could decide the appropriate action to take.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;The use (and conditions) of &lt;code&gt;panic&lt;/code&gt; should be documented (example: &lt;a href=&#34;https://github.com/golang/go/blob/8ac6544/src/bytes/buffer.go#L81&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;bytes.Truncate&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;The use of &lt;code&gt;recover&lt;/code&gt; is for when you disagree with the library authors.&lt;/li&gt;&#xA;&lt;li&gt;Wherever possible avoid &lt;code&gt;panic&lt;/code&gt; and return an error for the caller to handle.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-guide-to-slice-gotchas&#34;&gt;Quick guide to slice &amp;lsquo;gotchas&amp;rsquo;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The first gotcha to be aware of is that in Go assigning a new value to a parameter with &lt;code&gt;=&lt;/code&gt; won&amp;rsquo;t affect the argument in any way. So consider the following simple code that tries to append a value to a slice&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func addTwo(s []int) {&#xA;    s = append(s, 2)&#xA;}&#xA;&#xA;func main() {&#xA;    mySlice := []int{1}&#xA;    addTwo(mySlice)&#xA;    fmt.Println(mySlice)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will print &lt;code&gt;[1]&lt;/code&gt;, which is not what we want.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if you already understand that a slice is really a pointer to an internal struct type, then this might make this even more confusing because you would be of the understanding that you can modify a argument if it&amp;rsquo;s passed as a pointer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in this case, although a slice really is just a pointer to a struct, you have to remember that is an implementation detail and so you still have to explicitly define the parameter as a pointer type and pass it as such&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func addTwo(s *[]int) {&#xA;    *s = append(*s, 2)&#xA;}&#xA;&#xA;func main() {&#xA;    mySlice := []int{1}&#xA;    addTwo(&amp;amp;mySlice)&#xA;    fmt.Println(mySlice)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above version of the code will now correctly print &lt;code&gt;[1 2]&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;When taking a slice of a slice you might stumble into behaviour which appears confusing at first. The &lt;code&gt;cap&lt;/code&gt;, &lt;code&gt;len&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; fields might change, but the underlying array is not re-allocated, nor copied over and so modifications to the slice will modify the original backing array.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;There are more examples/explanations in &lt;a href=&#34;https://blogtitle.github.io/go-slices-gotchas/&#34; target=&#34;_blank&#34;&gt;https://blogtitle.github.io/go-slices-gotchas/&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;ghost-update-1&#34;&gt;Ghost update 1&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The underlying array is modified after updating an element on the slice as there is no re-allocation of the underlying array:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := []int{1, 2}&#xA;b := a[:1]     /* [1]     */&#xA;b[0] = 42      /* [42]    */&#xA;fmt.Println(a) /* [42, 2] */&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s likely you&amp;rsquo;ll want to set the capacity when taking a slice of &lt;code&gt;a&lt;/code&gt; to assign to &lt;code&gt;b&lt;/code&gt;. This will cause a new backing array to be created for the &lt;code&gt;b&lt;/code&gt; slice:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := []int{1, 2}&#xA;b := a[:1:2]   // [1]&#xA;b[0] = 42&#xA;fmt.Println(a) // [42, 2]&#xA;fmt.Println(b) // [42]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Refer to the golang language specification section on &lt;a href=&#34;https://golang.org/ref/spec#Slice_expressions&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;full slice expressions&amp;rdquo;&lt;/a&gt; syntax (&lt;code&gt;[low : high : max]&lt;/code&gt;) for controlling the capacity of a slice.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;ghost-update-2&#34;&gt;Ghost update 2&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When data gets appended to &lt;code&gt;b&lt;/code&gt; (a slice of the &lt;code&gt;a&lt;/code&gt; slice), the underlying array has enough capacity to hold two more elements, so &lt;code&gt;append&lt;/code&gt; will not re-allocate. This means that appending to &lt;code&gt;b&lt;/code&gt; might not only change &lt;code&gt;a&lt;/code&gt; but also &lt;code&gt;c&lt;/code&gt; (a slice of the &lt;code&gt;a&lt;/code&gt; slice).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := []int{1, 2, 3, 4}&#xA;b := a[:2] /* [1, 2] */&#xA;c := a[2:] /* [3, 4] */&#xA;b = append(b, 5)&#xA;fmt.Println(a) /* [1 2 5 4] */&#xA;fmt.Println(b) /* [1 2 5]   */&#xA;fmt.Println(c) /* [5 4]     */&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;fix&amp;rsquo;, like shown earlier, is &lt;code&gt;b := a[:2:2]&lt;/code&gt; which sets the capacity of the &lt;code&gt;b&lt;/code&gt; slice such that &lt;code&gt;append&lt;/code&gt; will cause a new array to be allocated. This means &lt;code&gt;a&lt;/code&gt; will not be modified, nor will the &lt;code&gt;c&lt;/code&gt; slice of &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-guide-to-pass-by-value-vs-pass-by-pointer&#34;&gt;Quick guide to pass-by-value vs pass-by-pointer&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reference articles: &lt;a href=&#34;https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/&#34; target=&#34;_blank&#34;&gt;goinbigdata.com&lt;/a&gt; and &lt;a href=&#34;https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go&#34; target=&#34;_blank&#34;&gt;dave.cheney.net&lt;/a&gt; and &lt;a href=&#34;https://www.alexedwards.net/blog/demystifying-function-parameters-in-go&#34; target=&#34;_blank&#34;&gt;alexedwards.net&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll commonly hear people use the phrase &amp;lsquo;pass-by-reference&amp;rsquo;. The behaviour this phrase describes is: &amp;ldquo;You&amp;rsquo;re not receiving a &lt;em&gt;copy&lt;/em&gt; of the thing being passed, you&amp;rsquo;re getting &lt;em&gt;direct access&lt;/em&gt; to it&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Go this behaviour is called &amp;lsquo;pass-by-pointer&amp;rsquo;. Whereas the phrase &amp;lsquo;pass by reference&amp;rsquo; is actually a very &lt;em&gt;specific&lt;/em&gt; type of behaviour (not supported in Go), and it&amp;rsquo;s not the same thing as &amp;lsquo;pass-by-pointer&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To understand pass-by-pointer we first thing to understand how arguments are passed to a function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All the following primitive/basic types in Go are passed as a &lt;em&gt;value&lt;/em&gt; (i.e. copied):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;array&lt;/li&gt;&#xA;&lt;li&gt;boolean&lt;/li&gt;&#xA;&lt;li&gt;float&lt;/li&gt;&#xA;&lt;li&gt;int&lt;/li&gt;&#xA;&lt;li&gt;string&lt;/li&gt;&#xA;&lt;li&gt;struct&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Whereas maps, slices, and channels are all passed by pointer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, here&amp;rsquo;s where I need to be more specific (and &lt;em&gt;accurate&lt;/em&gt;):&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In Go &lt;em&gt;every&lt;/em&gt; function operates on a &lt;em&gt;copy&lt;/em&gt; of the arguments passed into the function. No exceptions, that is what happens for every type.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;With the primitive/basic types, their &lt;em&gt;value&lt;/em&gt; is &lt;em&gt;copied&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So why is it that maps, slices and channels are passed by pointer?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, maps, slices and channels &lt;em&gt;are&lt;/em&gt; all pointers (you might not have realised that!). When you create an instance of one of these types, the Go language actually instantiates an &lt;em&gt;internal&lt;/em&gt; struct (e.g. a &lt;a href=&#34;https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/runtime/map.go#L117&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;runtime.hmap&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/runtime/slice.go#L15&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;runtime.slice&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/runtime/chan.go#L33C6-L33C11&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;runtime.hchan&lt;/code&gt;&lt;/a&gt;) and returns a pointer to them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A pointer is something that &lt;em&gt;points to&lt;/em&gt; a memory address.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As we&amp;rsquo;ve already said, Go will &lt;em&gt;always&lt;/em&gt; pass a &lt;em&gt;copy&lt;/em&gt; of an argument so Go doesn&amp;rsquo;t pass a pointer. Just like the primitive/basic types, it will create a &lt;em&gt;copy&lt;/em&gt; of the pointer and pass that. This still means the receiver can deference the copy of the pointer its given, to get at the underlying memory address (because the underlying address is still the same, even if the pointer is a copy).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now going back to a phrase that people commonly use when talking about Go: pass-by-reference. Go does not have pass-by-reference semantics because Go does not have &amp;lsquo;reference variables&amp;rsquo;, which is something you&amp;rsquo;d find in C++.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In C++ you can define:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-c++&#34;&gt;a = 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then you can &amp;lsquo;alias&amp;rsquo; &lt;code&gt;b&lt;/code&gt; to &lt;code&gt;a&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-c++&#34;&gt;&amp;amp;b = a&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In C++ this would mean updating &lt;code&gt;b&lt;/code&gt; would &lt;em&gt;affect&lt;/em&gt; &lt;code&gt;a&lt;/code&gt;. Go doesn&amp;rsquo;t have this behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Go, every variable is stored in its own memory space. Meaning, if we had &lt;code&gt;b := &amp;amp;a&lt;/code&gt; and updated &lt;code&gt;b&lt;/code&gt; then we wouldn&amp;rsquo;t cause any change to &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Go, imagine we define a function with a parameter &lt;code&gt;p&lt;/code&gt; which is of a pointer type:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func changeName(p *Person) {&#xA;    //&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now imagine we pass a pointer to that function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;changeName(&amp;amp;person)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We now know that Go will not pass the &lt;code&gt;&amp;amp;person&lt;/code&gt; pointer, but a &lt;em&gt;copy&lt;/em&gt; of the pointer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, if the &lt;code&gt;changeName&lt;/code&gt; function were to modify the &lt;code&gt;p&lt;/code&gt; argument variable it receives, this would actually cause the &lt;code&gt;person&lt;/code&gt; variable to be updated.&#xA;This happens because although the &lt;code&gt;&amp;amp;person&lt;/code&gt; pointer was copied into the function argument, the &lt;code&gt;&amp;amp;person&lt;/code&gt; and &lt;code&gt;p&lt;/code&gt; are two &lt;em&gt;different&lt;/em&gt; pointers to the &lt;em&gt;same&lt;/em&gt; struct which is stored at the same memory address. This is quite different to C++&amp;rsquo;s reference variables.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-guide-to-functions-with-large-signature&#34;&gt;Quick guide to functions with large signature&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Your functions should have concise/relevant arguments passed in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t, for example, pass in an argument whose type is a large and deeply nested object. Firstly, this means the consuming function has to know the structure well enough to dip into it (and arguably it could be argued that this violates the Law of Demeter). Secondly, it makes testing such a function tedious, and thirdly managing such a data structure is equally tedious. Instead choose a field from the object to pass in as it&amp;rsquo;ll likely have a simpler type (like a &lt;code&gt;string&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are four approaches to dealing with functions that potentially could have a large number of arguments&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Make multiple functions to help reduce the number of arguments.&lt;/li&gt;&#xA;&lt;li&gt;Pass in a &lt;code&gt;&amp;lt;T&amp;gt;Options&lt;/code&gt; struct.&lt;/li&gt;&#xA;&lt;li&gt;Variadic arguments that accept a func type (aka &amp;ldquo;functional options pattern&amp;rdquo;).&lt;/li&gt;&#xA;&lt;li&gt;Chaining methods on the configuration object (aka &amp;ldquo;builder pattern&amp;rdquo;).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;I would say go with option 1 whenever possible, and almost never choose option 2 over option 3 as the latter is much more flexible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with option 2 is that it can become quite cumbersome to construct an object with lots of fields, and more importantly it can be hard to know which fields are &lt;em&gt;required&lt;/em&gt; and which are &lt;em&gt;optional&lt;/em&gt;. Yes it&amp;rsquo;s nice that you can easily omit optional fields easily, but then option 3 also provides that benefit while also solving the problem of knowing what arguments are required vs optional.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using option 3 can be helpful when you want to make the function signature clear, by accepting a couple of concrete arguments that are &lt;em&gt;required&lt;/em&gt; for the function to work, while shifting &lt;em&gt;optional&lt;/em&gt; arguments into separate functions, as demonstrated below&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// Client is the complex type that needs to be constructed.&#xA;type Client struct {&#xA;  host string&#xA;  port int&#xA;}&#xA;&#xA;// Option is a function that is passed a pointer to the Client type.&#xA;// This is so the function can modify the Client.&#xA;type Option func(*Client)&#xA;&#xA;// WithPort returns an Option&#xA;func WithPort(port int) Option {&#xA;  return func(c *Client) { c.port = port }&#xA;}&#xA;&#xA;// NewClient will set the &#39;host&#39; while attempting to call all &#39;Option&#39; functions.&#xA;func NewClient(host string, options ...Option) *Client {&#xA;  c := &amp;amp;Client{host: host, port: 80} // default values&#xA;  for _, option := range options {&#xA;    option(c) // apply the options by calling each one of them&#xA;&#xA;    // Essentially, for this example code, there is noly one Option passed.&#xA;    // The Option being called is: &#xA;    // func(c *Client) { c.port = port }&#xA;  }&#xA;  return c&#xA;}&#xA;&#xA;c := NewClient(&amp;quot;httpbin.org&amp;quot;) // only &#39;host&#39; is required &#xA;c := NewClient(&amp;quot;httpbin.org&amp;quot;, WithPort(443)) // WithPort is called and returns an Option type&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The downside to option 3 is that it&amp;rsquo;s hard to know the &lt;code&gt;With*&lt;/code&gt; functions exist&#xA;as they live at the package level and aren&amp;rsquo;t directly associated with the&#xA;&lt;code&gt;*Client&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So option 4 helps with that:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;)&#xA;&#xA;// Client is the complex type that needs to be constructed.&#xA;type Client struct {&#xA;    host string&#xA;    port int&#xA;}&#xA;&#xA;// WithPort returns a mutated *Client type.&#xA;func (c *Client) WithPort(port int) *Client {&#xA;    c.port = port&#xA;    return c&#xA;}&#xA;&#xA;// NewClient returns the initial *Client type with required host set and the&#xA;// optional port set to port 80.&#xA;func NewClient(host string) *Client {&#xA;    return &amp;amp;Client{host: host, port: 80} // default value for port&#xA;}&#xA;&#xA;func main() {&#xA;    c := NewClient(&amp;quot;httpbin.org&amp;quot;)&#xA;    fmt.Printf(&amp;quot;%#v\n&amp;quot;, c) // &amp;amp;main.Client{host:&amp;quot;httpbin.org&amp;quot;, port:80}&#xA;    c = NewClient(&amp;quot;httpbin.org&amp;quot;).WithPort(443)&#xA;    fmt.Printf(&amp;quot;%#v\n&amp;quot;, c) // &amp;amp;main.Client{host:&amp;quot;httpbin.org&amp;quot;, port:443}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t like the &amp;ldquo;chaining&amp;rdquo; pattern because it reminds me of jQuery (which made&#xA;this approach famous in the world of JavaScript) but it&amp;rsquo;s hard to deny that the&#xA;methods are definitely more &lt;em&gt;discoverable&lt;/em&gt; than the functional options pattern.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-style-guide/</guid>
      <link>https://www.integralist.co.uk/posts/go-style-guide/</link>
      <pubDate>Tue, 11 Jan 2022 00:00:00 +0000</pubDate>
      <title>Go Style Guide</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/features/actions&#34; target=&#34;_blank&#34;&gt;GitHub Actions&lt;/a&gt; makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve been using GitHub Actions a lot recently and I&amp;rsquo;ve found it to be immensely flexible and feature rich. I think it&amp;rsquo;s well worth your time learning how to run your CI/CD pipelines via GitHub Actions, and in this post that&amp;rsquo;s exactly what we&amp;rsquo;re going to dig into.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It all starts with a &amp;lsquo;workflow&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A workflow is a yaml configuration file that defines:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Jobs&lt;/strong&gt;: a job represents a collection of &amp;lsquo;steps&amp;rsquo;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Steps&lt;/strong&gt;: each &amp;lsquo;step&amp;rsquo; does something useful (e.g. executes a piece of code).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Events&lt;/strong&gt;: an event determines when your &amp;lsquo;jobs&amp;rsquo; should run.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;GitHub has a nice visualisation of this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/overview-actions-simple.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/overview-actions-simple.png&#34; alt=&#34;overview actions simple&#34; /&gt;&lt;/a&gt;&#xA;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Each job you define will run in parallel. If you need jobs to run sequentially, then you&amp;rsquo;ll need to configure a job to depend on another job using the &lt;code&gt;needs&lt;/code&gt; property (we&amp;rsquo;ll see an example of this later).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;documentation&#34;&gt;Documentation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I would strongly suggest bookmarking the &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt; because it&amp;rsquo;s very thorough. Unfortunately it&amp;rsquo;s so thorough that it can be a bit overwhelming, but don&amp;rsquo;t worry, once you&amp;rsquo;ve gotten familiar with the various concepts you&amp;rsquo;ll start to remember where the important information is located.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The pages I use the most are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/expressions&#34; target=&#34;_blank&#34;&gt;Expressions&lt;/a&gt;&lt;/strong&gt;: explains how to use GitHub&amp;rsquo;s builtin functions, like &lt;code&gt;contains()&lt;/code&gt;, &lt;code&gt;fromJSON()&lt;/code&gt;, and functions like &lt;code&gt;success()&lt;/code&gt; and &lt;code&gt;failure()&lt;/code&gt; that tell you the state of previous steps that have run.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/contexts&#34; target=&#34;_blank&#34;&gt;Contexts&lt;/a&gt;&lt;/strong&gt;: there are lots of contextual objects your jobs can use, such as objects for getting information about git (what branch we&amp;rsquo;re dealing with, the commit SHA etc), environment variables, secrets, data exposed by other jobs and lots more.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions&#34; target=&#34;_blank&#34;&gt;Syntax&lt;/a&gt;&lt;/strong&gt;: this is the most important page as it details all the yaml configuration syntax (so I come here often).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions&#34; target=&#34;_blank&#34;&gt;Commands&lt;/a&gt;&lt;/strong&gt;: when executing a shell command (or script) you can use &lt;code&gt;echo&lt;/code&gt; with a specific format and, depending on the format used, it&amp;rsquo;ll take on special meaning to the workflow runner and can be used (among other things) for displaying rich messaging in the GitHub UI.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/environment-variables&#34; target=&#34;_blank&#34;&gt;Environment variables&lt;/a&gt;&lt;/strong&gt;: most of the &amp;lsquo;context&amp;rsquo; properties are also exposed as environment variables to make it easier for your shell commands/scripts to utilise.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/reusing-workflows&#34; target=&#34;_blank&#34;&gt;Reusing workflows&lt;/a&gt;&lt;/strong&gt;: If you have a bunch of jobs all doing a similar thing (e.g. you&amp;rsquo;ve three jobs and each of them setup a specific set of environment variables before installing the rust programming language), then you can move that duplication into a separate workflow file that your main workflow can call out to.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;experimenting&#34;&gt;Experimenting&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The best thing to do when it comes to learning GitHub Actions is to create a test repo as a playground, like I did here: &lt;a href=&#34;https://github.com/Integralist/actions-testing&#34; target=&#34;_blank&#34;&gt;https://github.com/Integralist/actions-testing&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can of course use an existing repo if you want, but I prefer to use something completely decoupled when I&amp;rsquo;m testing a new tool.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;workflows&#34;&gt;Workflows&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As I mentioned earlier: everything starts with a workflow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To create a workflow you must save a yaml file into the &lt;code&gt;.github/workflows&lt;/code&gt; directory of your project&amp;rsquo;s git repo.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example you&amp;rsquo;ll see I have created three separate workflows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;├── .github&#xA;│   └── workflows&#xA;│       ├── my-first-workflow.yaml&#xA;│       ├── my-second-workflow.yaml&#xA;│       └── my-third-workflow.yaml&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can create as many workflows as you need to, and you can name a workflow file anything you like.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;events&#34;&gt;Events&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Once we create a workflow file, let&amp;rsquo;s see how we can trigger any jobs that are defined within the workflow. Be aware that in the following example workflow I have not defined any jobs, I&amp;rsquo;m focusing on the events configuration only:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: My Workflow&#xA;on:&#xA;  push:&#xA;  schedule:&#xA;    - cron: &amp;quot;0 0 1 * *&amp;quot;   # https://crontab.guru/every-month&#xA;    - cron: &amp;quot;*/5 * * * *&amp;quot; # https://crontab.guru/every-5-minutes&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see I&amp;rsquo;ve given my workflow a name using the &lt;code&gt;name&lt;/code&gt; key, and I&amp;rsquo;ve defined some events using the &lt;code&gt;on&lt;/code&gt; key:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;push&lt;/code&gt;: any push to your repo, whether it be to your &lt;code&gt;main&lt;/code&gt; branch or a pull-request branch, will trigger your job(s) to run.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;schedule&lt;/code&gt;: run your job(s) on a schedule using cron syntax, which in this example triggers job(s) every five minutes and monthly.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://crontab.guru/&#34; target=&#34;_blank&#34;&gt;https://crontab.guru/&lt;/a&gt; makes dealing with cron syntax easy.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Refer to GitHub&amp;rsquo;s &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows&#34; target=&#34;_blank&#34;&gt;events documentation&lt;/a&gt; to learn more about the various events you can configure. For example, you can restrict a workflow to only execute against a specific branch.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;environment&#34;&gt;Environment&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each job runs inside its own virtual machine &amp;lsquo;runner&amp;rsquo;, which means (just as an example) files you create, or data you produce, will not persist across jobs. This includes things like environment variables.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;example-job&#34;&gt;Example Job&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at a very simple job:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Test Workflow&#xA;on: push&#xA;jobs:&#xA;  simple-job:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - name: Say Hello&#xA;        run: echo &#39;hello&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now break apart this workflow to understand what it&amp;rsquo;s doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;name&lt;/code&gt;: the name for the workflow.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;on&lt;/code&gt;: the event(s) we want to have trigger our job(s).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;jobs&lt;/code&gt;: a list of jobs we want to be executed under this workflow.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;simple-job&lt;/code&gt;: a job that consists of nested configuration.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;runs-on&lt;/code&gt;: the environment I want the job to run in.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;steps&lt;/code&gt;: a list of steps to run under the job.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;name&lt;/code&gt;: the name of the step, which can be omitted but it makes the output in the GitHub UI nicer.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;run&lt;/code&gt;: the shell command/script I want to run (in this example, my command prints the string &lt;code&gt;hello&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Refer to the GitHub &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#github-hosted-runners&#34; target=&#34;_blank&#34;&gt;runner documentation&lt;/a&gt; to see what other environments are available. Also refer to the &lt;a href=&#34;https://github.com/actions/virtual-environments&#34; target=&#34;_blank&#34;&gt;virtual-environments&lt;/a&gt; repo to see what is installed on each runner&amp;rsquo;s operating system.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;As you can see, defining a workflow and its jobs/steps is actually very simple and intuitive. Now we can start looking at using more features and how to take advantage of the platform.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;environment-variables&#34;&gt;Environment Variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;GitHub Actions let you configure environment variables in multiple places depending on the scope they should have.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can define environment variables globally, so they&amp;rsquo;re available to all jobs (and all steps within those jobs), or at a job level (so they can be accessed by all steps within the specific job) or at a step level, meaning only a specific step will have access to them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll demonstrate environment variable configuration in the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Testing Environment Variables&#xA;on: push&#xA;env:&#xA;  FOO: bar&#xA;jobs:&#xA;  validate-env-vars:&#xA;    runs-on: ubuntu-latest&#xA;    env:&#xA;      LITERAL: whatever&#xA;      INTERPOLATION: ${{ github.ref_name }}&#xA;      EXPRESSION: $(echo ${{ github.ref_name }} | \&#xA;        perl -pe &#39;s/[^a-zA-Z0-9]+/-/g&#39; | \&#xA;        perl -pe &#39;s/(\A-|-\Z)//g&#39; | \&#xA;        awk &#39;{print tolower($0)}&#39;)&#xA;    steps:&#xA;      - name: Print Global Environment Variables&#xA;        run: echo $FOO&#xA;      - name: Print Job Environment Variables&#xA;        run: |&#xA;          echo ${{ env.LITERAL }}&#xA;          echo ${{ env.INTERPOLATION }}&#xA;          echo ${{ env.EXPRESSION }}&#xA;          echo $LITERAL&#xA;          echo $INTERPOLATION&#xA;          echo $EXPRESSION&#xA;      - name: Print Step Environment Variables:&#xA;        env:&#xA;          STEPVAR: my step&#xA;        run: |&#xA;          echo ${{ env.STEPVAR }}&#xA;          echo $STEPVAR&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so there&amp;rsquo;s a few things to unpack from the above example workflow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first thing I want to clarify is that when running shell commands/scripts using &lt;code&gt;steps.run&lt;/code&gt; you can either define multiple steps like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- run: echo hello&#xA;- run: echo world&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or alternatively you can use the pipe &lt;code&gt;|&lt;/code&gt; character to indicate the value spans multiple lines, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- run: |&#xA;  echo hello&#xA;  echo world&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I would tend towards using separate &lt;code&gt;run&lt;/code&gt; steps rather than one long multi-line &lt;code&gt;run&lt;/code&gt; because it&amp;rsquo;s harder to handle errors (or know where an error occurred) in the latter approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing to clarify is that there are two ways to access an environment variable:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Interpolation&lt;/strong&gt;: &lt;code&gt;${{ ... }}&lt;/code&gt; (e.g. &lt;code&gt;echo ${{ env.LITERAL }}&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Variable reference&lt;/strong&gt;: &lt;code&gt;$VARNAME&lt;/code&gt; (e.g. &lt;code&gt;echo $LITERAL&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to understand that although the output between the two approaches is the same, there is still a distinction worth being aware of.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With interpolation the value is acquired by looking up the relevant key within the &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/contexts#env-context&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;env&lt;/code&gt; context object&lt;/a&gt;, and then the value is injected into the shell command to be executed, while the more traditional variable reference approach works by the shell instance looking up the environment variable to access the value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So when you look at the GitHub Actions GUI (e.g. &lt;code&gt;https://github.com/&amp;lt;USER&amp;gt;/&amp;lt;REPO&amp;gt;/actions/runs/&amp;lt;ID&amp;gt;&lt;/code&gt;) and you look through the job output for the &lt;code&gt;LITERAL&lt;/code&gt; example, then you&amp;rsquo;ll see something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo whatever&#xA;echo $LITERAL&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is because the first line used interpolation, so really the shell command was just echo&amp;rsquo;ing the literal value, where as the second line was echo&amp;rsquo;ing the &lt;em&gt;result&lt;/em&gt; of looking up the environment variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In our example workflow you can see we defined a global environment variable called &lt;code&gt;FOO&lt;/code&gt;, we also defined a job level set of environment variables (&lt;code&gt;LITERAL&lt;/code&gt;, &lt;code&gt;INTERPOLATED&lt;/code&gt; and &lt;code&gt;EXPRESSION&lt;/code&gt;), and finally we defined a step level environment variable called &lt;code&gt;STEPVAR&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a moment to clarify the job level environment variables as these demonstrate something important, which is although the &lt;code&gt;EXPRESSION&lt;/code&gt; variable was assigned a shell command, that command isn&amp;rsquo;t &lt;em&gt;evaluated&lt;/em&gt; and so the literal characters are assigned as the value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you thought the &lt;em&gt;result&lt;/em&gt; of the shell command (e.g. acquire the branch name from the &lt;code&gt;github&lt;/code&gt; context object, and then do some normalisation of the name using a combination of &lt;code&gt;perl&lt;/code&gt; and &lt;code&gt;awk&lt;/code&gt;) would be assigned to the environment variable, then you would have been wrong.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Only the &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsrun&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;steps.run&lt;/code&gt;&lt;/a&gt; key will actually evaluate a given shell command/script.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if the only way to evaluate a shell command is via &lt;code&gt;steps.run&lt;/code&gt;, then how can we dynamically assign a value to an environment variable?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider this example, you&amp;rsquo;re a &lt;a href=&#34;https://nodejs.org/en/&#34; target=&#34;_blank&#34;&gt;Node.js&lt;/a&gt; developer and you&amp;rsquo;re using the Node version manager &lt;code&gt;nvm&lt;/code&gt; along with a &lt;a href=&#34;https://github.com/nvm-sh/nvm#nvmrc&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;.nvmrc&lt;/code&gt; file&lt;/a&gt; to control which version of Node your project uses.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;re also using GitHub actions and you want to use a pre-existing action to manage installing Node on your job runner (we&amp;rsquo;ll dig into third-party actions later, but for now just know that they are a thing).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where things get a little funky, because third-party actions can&amp;rsquo;t evaluate shell commands given as inputs. So the most popular third-party action for installing Node is &lt;a href=&#34;https://github.com/actions/setup-node&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/setup-node&lt;/code&gt;&lt;/a&gt; and it allows you to specify the version of Node to install but it has to be a literal value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how to side-step this restriction by using a &lt;code&gt;steps.run&lt;/code&gt; to dynamically access the value inside the &lt;code&gt;.nvmrc&lt;/code&gt; file and to then update the local environment with a new variable holding that value. This means you can then use interpolation to access that value and pass it into the &lt;code&gt;actions/setup-node&lt;/code&gt; action:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Testing Dynamic Environment Variable Value&#xA;on: push&#xA;jobs:&#xA;  validate-env-vars:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - name: Generate Dynamic Environment Variable&#xA;        run: echo &amp;quot;NODE_VERSION=$(cat .nvmrc)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;      - name: Print NODE_VERSION&#xA;        run: |&#xA;          echo ${{ env.NODE_VERSION }}&#xA;          echo $NODE_VERSION&#xA;      - uses: actions/setup-node@v2&#xA;        with:&#xA;          node-version: &amp;quot;${{ env.NODE_VERSION }}&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The trick is to update a GitHub Actions provided environment variable called &lt;code&gt;$GITHUB_ENV&lt;/code&gt;. All the following steps will then have an environment that includes whatever is in &lt;code&gt;$GITHUB_ENV&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You could also use the output of a step as the input to the &lt;code&gt;actions/setup-node&lt;/code&gt; action, but we&amp;rsquo;ll look at that feature later.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;secrets&#34;&gt;Secrets&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The previous Node.js example workflow actually leads us quite nicely into this section about &lt;a href=&#34;https://docs.github.com/en/actions/security-guides/encrypted-secrets#using-encrypted-secrets-in-a-workflow&#34; target=&#34;_blank&#34;&gt;secrets&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see a common solution to accessing a private NPM repository&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Testing GITHUB_TOKEN access restrictions&#xA;on: push&#xA;jobs:&#xA;  testing:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - name: Acquire Node Version&#xA;        run: echo &amp;quot;NODE_VERSION=$(cat .nvmrc)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;      - uses: actions/setup-node@v2&#xA;        with:&#xA;          node-version: &amp;quot;${{ env.NODE_VERSION }}&amp;quot;&#xA;      - name: Authorize access to private packages&#xA;        run: echo &amp;quot;//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}&amp;quot; &amp;gt; ~/.npmrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What we&amp;rsquo;re doing here is installing Node.js and then modifying a &lt;code&gt;.npmrc&lt;/code&gt; file so that it knows, when we do an &lt;code&gt;npm install&lt;/code&gt;, to use an authentication token because the repository we want to use to get at our dependencies is otherwise private.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll see we&amp;rsquo;re using a &lt;a href=&#34;https://docs.github.com/en/actions/security-guides/encrypted-secrets&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;secrets&lt;/code&gt; context object&lt;/a&gt; to access a &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; value to use as our authentication token. This should be fine, but it doesn&amp;rsquo;t work and our authentication with the private NPM repository fails.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a moment to learn a bit about GitHub &amp;lsquo;secrets&amp;rsquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the GitHub UI for a repo/project you can add secrets that are encrypted and made accessible to your workflow via the &lt;code&gt;secrets&lt;/code&gt; context object. But additionally GitHub Actions provides access to a secret called &lt;a href=&#34;https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;GITHUB_TOKEN&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll just refer you to the GitHub documentation, as it explains it best:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;At the start of each workflow run, GitHub automatically creates a unique GITHUB_TOKEN secret to use in your workflow. When you enable GitHub Actions, GitHub installs a GitHub App on your repository. The GITHUB_TOKEN secret is a GitHub App installation access token. You can use the installation access token to authenticate on behalf of the GitHub App installed on your repository. The token&amp;rsquo;s permissions are limited to the repository that contains your workflow.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;That last sentence is the important bit! What essentially it means is that you can&amp;rsquo;t use &lt;code&gt;secrets.GITHUB_TOKEN&lt;/code&gt; to access things outside of the project repo.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to solve our problem we still need to use the &lt;code&gt;secrets&lt;/code&gt; context object, but instead of using the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; we&amp;rsquo;re going to need to create a new &lt;a href=&#34;https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token&#34; target=&#34;_blank&#34;&gt;Personal Access Token&lt;/a&gt; (PAT).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you create a PAT, as long as the user account that creates the PAT has access to the private repository, we can paste the PAT into the GitHub secrets UI.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the sake of an example let&amp;rsquo;s say you create a new secret called &lt;code&gt;NPM_AUTH_TOKEN&lt;/code&gt; and paste the PAT value into it. We can now reference the secret token value via the &lt;code&gt;secrets&lt;/code&gt; context object in our workflow file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Testing with Personal Access Token&#xA;on: push&#xA;jobs:&#xA;  testing:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - name: Acquire Node Version&#xA;        run: echo &amp;quot;NODE_VERSION=$(cat .nvmrc)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;      - uses: actions/setup-node@v2&#xA;        with:&#xA;          node-version: &amp;quot;${{ env.NODE_VERSION }}&amp;quot;&#xA;      - name: Authorize access to private packages&#xA;        run: echo &amp;quot;//npm.pkg.github.com/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}&amp;quot; &amp;gt; ~/.npmrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that the workflow file basically hasn&amp;rsquo;t changed, except we swapped &lt;code&gt;secrets.GITHUB_TOKEN&lt;/code&gt; for &lt;code&gt;secrets.NPM_AUTH_TOKEN&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;third-party-actions&#34;&gt;Third Party Actions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An action is just code that interacts with your repository. It&amp;rsquo;s possible to write your own custom actions and to share them with the community.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to learn more about creating your own actions, then refer to GitHub&amp;rsquo;s &amp;ldquo;&lt;a href=&#34;https://docs.github.com/en/actions/creating-actions/about-custom-actions&#34; target=&#34;_blank&#34;&gt;About custom actions&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a bunch of third-party actions that you&amp;rsquo;ll see used a lot&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/actions/checkout&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/checkout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/actions/cache&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/cache&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/actions/setup-go&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/setup-go&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/actions/setup-node&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/setup-node&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/actions-rs/toolchain&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions-rs/toolchain&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All of the above actions, with the exception of the last, are official GitHub maintained actions. This means they are considered safe to use in your workflows (remember that an action runner will be able to use your &lt;code&gt;secrets.GITHUB_TOKEN&lt;/code&gt;). See also &lt;a href=&#34;https://github.com/actions&#34; target=&#34;_blank&#34;&gt;https://github.com/actions&lt;/a&gt; for more official/verified actions you can use.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve no idea why they don&amp;rsquo;t provide a Rust action.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conditions&#34;&gt;Conditions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You can use an &lt;code&gt;if&lt;/code&gt; conditional statement to control whether a job or step is run. It&amp;rsquo;s best to use this feature if you need to &lt;em&gt;skip&lt;/em&gt; a job/step apposed to using an exit code from within a &lt;code&gt;run&lt;/code&gt; shell command/script to stop a job/step that has already started to run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One important caveat to using &lt;code&gt;if&lt;/code&gt; in a workflow is that you &lt;em&gt;must&lt;/em&gt; use single quotes and not double quotes. Consider the following example, which you might expect to only run the job if the GitHub branch affected is &lt;code&gt;main&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Testing with Double Quotes&#xA;on: push&#xA;jobs:&#xA;  run-if-main:&#xA;    if: ${{ github.ref_name == &amp;quot;main&amp;quot; }}&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - run: echo hello&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Expressions can omit the surrounding &lt;code&gt;${{ ... }}&lt;/code&gt; but I tend to include it.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The above example won&amp;rsquo;t work simply because the string &lt;code&gt;&amp;quot;main&amp;quot;&lt;/code&gt; is using double quotes. You&amp;rsquo;ll find the requirement for using single quotes is mentioned in the GitHub documentation for &amp;ldquo;&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/expressions#literals&#34; target=&#34;_blank&#34;&gt;Literals&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to learn more about the available operators, like &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt; and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; etc, then refer to the &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/expressions#operators&#34; target=&#34;_blank&#34;&gt;operators documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;persisting-data&#34;&gt;Persisting Data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A GitHub Action job does not persist data by default, as each job runs within its own &amp;lsquo;runner&amp;rsquo;. To persist data we can use either a:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Cache (&lt;a href=&#34;https://github.com/actions/cache&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/cache&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Artifact (&lt;a href=&#34;https://github.com/actions/upload-artifact&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/upload-artifact&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://github.com/actions/download-artifact&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;actions/download-artifact&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Job Output (&lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idoutputs&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;outputs&lt;/code&gt; documenation&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Caching is quick but isn&amp;rsquo;t always ideal as it requires the use of I/O to create files to be cached, and then also we have to coordinate reading values back from disk and parsing the data contained within those files etc. Caching is best used for simple situations such as caching installed programming language dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Artifacts are slow as they need to upload and download files from GitHub&amp;rsquo;s servers and also this requires two separate external actions to configure, making them not ideal for quick data persistence (and also makes &amp;lsquo;simple&amp;rsquo; data persistence scenarios tedious).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To persist data using a job&amp;rsquo;s output requires a job to produce some data and to expose that data via the job&amp;rsquo;s &lt;code&gt;outputs&lt;/code&gt; field. A consumer can then use and parse that data however they see fit. This approach can also be useful for dynamically generating job matrix variants using a job&amp;rsquo;s &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstrategy&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;strategy.matrix&lt;/code&gt;&lt;/a&gt; field.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;A job has an &lt;code&gt;outputs&lt;/code&gt; field, but also individual steps can access the output from a previous step by way of the same mechanism, which is a step needs to set an &lt;code&gt;id&lt;/code&gt; field which either another step or the job itself can reference.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The way your &lt;code&gt;run&lt;/code&gt; code (or an external shell script) can produce data that the GitHub job can reference is to &lt;code&gt;echo&lt;/code&gt; a specially formatted string:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;::set-output name=&amp;lt;name&amp;gt;::&amp;lt;data&amp;gt;&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So in the following example we produce the data &lt;code&gt;bar&lt;/code&gt; and we make it accessible via the name &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;echo &amp;quot;::set-output name=foo::bar&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now in the following example our GitHub job has two steps, and the latter step is accessing data produced by the first step:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Produce Data&#xA;on: push&#xA;jobs:&#xA;  example:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - id: produce-data&#xA;        run: echo &amp;quot;::set-output name=foo::bar&amp;quot;&#xA;      - run: echo ${{ steps.produce-data.outputs.foo }}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Be sure to use the &lt;code&gt;id&lt;/code&gt; field so the second step can use it to reference the first step&amp;rsquo;s output!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;using-shared-job-data-to-determine-if-subsequent-job-should-run&#34;&gt;Using shared job data to determine if subsequent job should run&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the following example the &lt;code&gt;bar&lt;/code&gt; job will not run if the required fields &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt; aren&amp;rsquo;t set to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice the data I produce within job &lt;code&gt;foo&lt;/code&gt; is a simple array/list whose elements are strings who have a format of &lt;code&gt;key=value&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Produce Data To Control Job Run&#xA;on: push&#xA;jobs:&#xA;  foo:&#xA;    runs-on: ubuntu-latest&#xA;    outputs:&#xA;      data: ${{ steps.footest.outputs.data }}&#xA;    steps:&#xA;      - run: |&#xA;          echo &amp;quot;FOO=true&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;          echo &amp;quot;BAR=false&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;          echo &amp;quot;BAZ=true&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;      - id: footest&#xA;        run: echo ::set-output name=data::[\&amp;quot;foo=$FOO\&amp;quot;, \&amp;quot;bar=$BAR\&amp;quot;, \&amp;quot;baz=$BAZ\&amp;quot;]&#xA;&#xA;  bar:&#xA;    needs: foo&#xA;    if: ${{ contains(needs.foo.outputs.data, &#39;foo=true&#39;) &amp;amp;&amp;amp; contains(needs.foo.outputs.data, &#39;baz=true&#39;) }}&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - run: echo &#39;yay! we ran because the fields were set to true&#39;&#xA;&#xA;  build:&#xA;    needs: bar&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - run: echo &#39;yay! this job ran as the bar job was successful&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The key part to getting job &lt;code&gt;bar&lt;/code&gt; to determine if it should run is to use an &lt;code&gt;if&lt;/code&gt; along with one of GitHub&amp;rsquo;s native functions called &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/expressions#contains&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;contains()&lt;/code&gt;&lt;/a&gt;. You can see I use it twice to check if the persisted data contains the values I&amp;rsquo;m looking for.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You&amp;rsquo;ll likely want to use the &lt;code&gt;needs&lt;/code&gt; property to help make the jobs run sequentially. Otherwise without it the jobs will run in parallel and this means there would be a data race in &lt;code&gt;bar&lt;/code&gt; trying to access the &lt;code&gt;foo&lt;/code&gt; job&amp;rsquo;s output which might not yet be available and this would cause both the &lt;code&gt;bar&lt;/code&gt; job and its dependant &lt;code&gt;build&lt;/code&gt; job to not be run.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;persist-data-using-strategy-matrix&#34;&gt;Persist data using &lt;code&gt;strategy.matrix&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Below is an example of using JSON data from &lt;code&gt;job1&lt;/code&gt; and exposing it to &lt;code&gt;job2&lt;/code&gt;. This approach of using &lt;a href=&#34;https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;fromJSON&lt;/code&gt;&lt;/a&gt; with data from another job to create a matrix is really cool, but otherwise this approach (as far as data persistence is concerned) isn&amp;rsquo;t ideal because it requires the JSON data produced by the first job to have a very specific structure that the &lt;code&gt;strategy.matrix&lt;/code&gt; expects. So to reiterate I&amp;rsquo;m not using &lt;code&gt;strategy.matrix&lt;/code&gt; in this example because I want a matrix but just to demonstrate a clever way to persist data without having to resort to using either caching or artifacts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this in mind I needed to ensure I set the value of each matrix field to be a &lt;em&gt;list&lt;/em&gt; type that contains a &lt;em&gt;single&lt;/em&gt; entry.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I didn&amp;rsquo;t use a list type then the &lt;code&gt;strategy.matrix&lt;/code&gt; would fail to parse my JSON data. I purposely ensure there is only a single value within the list because I don&amp;rsquo;t actually need my data to cause the job to be run multiple times. This is because a &lt;code&gt;strategy.matrix&lt;/code&gt; is typically used to generate multiple &amp;lsquo;variants&amp;rsquo; of a job. By setting a single value inside a list, we ensure there is only ever one job variant generated (i.e. only one job is created), and that single job can simply reference the fields within the matrix as data points of interest.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: example&#xA;on: push&#xA;jobs:&#xA;  job1:&#xA;    runs-on: ubuntu-latest&#xA;    outputs:&#xA;      matrix: ${{ steps.set-matrix.outputs.matrix }}&#xA;    steps:&#xA;      - id: set-matrix&#xA;        run: echo &amp;quot;::set-output name=matrix::{\&amp;quot;FOO\&amp;quot;:[&amp;quot;abc&amp;quot;],\&amp;quot;BAR\&amp;quot;:[&amp;quot;xyz&amp;quot;]}&amp;quot;&#xA;  job2:&#xA;    needs: job1&#xA;    runs-on: ubuntu-latest&#xA;    strategy:&#xA;      matrix: ${{fromJSON(needs.job1.outputs.matrix)}}&#xA;    env:&#xA;      FOO: ${{ matrix.FOO }}&#xA;      BAR: ${{ matrix.BAR }}&#xA;    steps:&#xA;      - run: echo ${{ matrix.FOO }} # abc&#xA;      - run: echo ${{ matrix.BAR }} # xyz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;clarify-the-cache-action&#34;&gt;Clarify the cache action&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, so as far as data persistence is concerned, we have the &lt;code&gt;actions/cache&lt;/code&gt; action we can use as an option. It&amp;rsquo;s actually not very obvious how this action works and so I thought I&amp;rsquo;d take a brief moment to clarify my understanding, which then helped me to better understand how I could use it for data persistence outside of just caching language dependencies (which is what most examples are based on).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;actions/cache@v2&lt;/code&gt; works like so, you have to define a new step like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- uses: actions/cache@v2&#xA;  with:&#xA;    path: path/to/be/cached&#xA;    key: ${{ runner.os }}-my-cache-key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When the step that implements the action is executed (see above snippet), the cache action simply looks up the cache key (e.g. &lt;code&gt;Linux-my-cache-key&lt;/code&gt;) and if it finds something in the cache, then it restores the cache to the path you specified (e.g. &lt;code&gt;path/to/be/cached&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the cache action doesn&amp;rsquo;t find anything in the cache, then nothing happens.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the important bit: the cache action has a &amp;lsquo;post run&amp;rsquo; event that executes once your job has finished successfully. The cache action will be run again and this time it stores whatever was in your given path into the cache using the key you said it should be stored under.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means, when it comes to running another job, you need to ensure you define the cache action &lt;em&gt;again&lt;/em&gt; (the same as you defined it in your first job). This is so all of what I&amp;rsquo;ve just explained will happen again in your second job (i.e. it&amp;rsquo;ll lookup the key but this time it&amp;rsquo;ll find something in the cache thanks to the &amp;lsquo;post run&amp;rsquo; step from the first job). The only difference now in the second job is that in the &amp;lsquo;post run&amp;rsquo; event, when the action gets run again, you&amp;rsquo;ll now see something like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Cache hit occurred on the primary key &lt;code&gt;Linux-my-cache-key&lt;/code&gt;, not saving cache.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Meaning there was nothing else to do. I imagine if there were changes to the files in the given path then it would indicate the cache was updated with the latest files.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reusable-workflows&#34;&gt;Reusable Workflows&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have a bunch of setup configuration that is the same between jobs, then you can move that configuration into a separate workflow file that can then be imported and used by each job in your main workflow file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example, demonstrates how to &lt;em&gt;call&lt;/em&gt; (i.e. import) a reusable workflow:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;jobs:&#xA;  build:&#xA;    ...&#xA;&#xA;  deploy:&#xA;    ...&#xA;&#xA;  validate-foo:&#xA;    uses: integralist/actions-testing/.github/workflows/resuable-setup@main # install node, rust, setup env vars etc&#xA;    steps: &#xA;      - ...&#xA;&#xA;  validate-bar:&#xA;    uses: integralist/actions-testing/.github/workflows/resuable-setup@main # install node, rust, setup env vars etc&#xA;    steps: &#xA;      - ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An example implementation of a reusable workflow would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;name: Reusable workflow for validation scripts&#xA;on:&#xA;  workflow_call:&#xA;    inputs:&#xA;      install_node:&#xA;        type: bool&#xA;      name:&#xA;        required: true&#xA;        type: string&#xA;      description:&#xA;        required: true&#xA;        type: string&#xA;      script:&#xA;        required: true&#xA;        type: string&#xA;&#xA;jobs:&#xA;  validation:&#xA;    runs-on: ubuntu-latest&#xA;    steps:&#xA;      - uses: actions/checkout@v2&#xA;      - if: ${{ github.event_name != &#39;schedule&#39; }}&#xA;        run: exit 1&#xA;      - if: ${{ inputs.install_node }}&#xA;        name: Environment&#xA;        run: |&#xA;          echo &amp;quot;NODE_VERSION=$(cat .nvmrc)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&#xA;      - if: ${{ inputs.install_node }}&#xA;        uses: actions/setup-node@v2&#xA;        id: node-yarn&#xA;        with:&#xA;          node-version: &amp;quot;${{ env.NODE_VERSION }}&amp;quot;&#xA;          cache: yarn&#xA;      - name: status update&#xA;        uses: ouzi-dev/commit-status-updater@v1.1.2&#xA;        with:&#xA;          name: ${{ inputs.name }}&#xA;          description: ${{ inputs.description }}&#xA;          status: pending&#xA;      - id: validator&#xA;        run: ${{ inputs.script }}&#xA;      - if: ${{ success() }}&#xA;        name: status update&#xA;        uses: ouzi-dev/commit-status-updater@v1.1.2&#xA;        with:&#xA;          name: ${{ inputs.name }}&#xA;          description: ${{ steps.validator.outputs.description }}&#xA;          status: ${{ steps.validator.outputs.status }}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that in the reusable workflow we have a new event &lt;code&gt;workflow_call&lt;/code&gt; that helps us to define &lt;em&gt;inputs&lt;/em&gt; for the job being called.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this reusable job we define a bunch of inputs which helps us to control whether the steps in the job are run (making the reusable job even more flexible) by utilising a step&amp;rsquo;s &lt;code&gt;if&lt;/code&gt; condition and interpolating the input value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, we don&amp;rsquo;t always install the Node.js programming language, only if the caller requests it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;- if: ${{ inputs.install_node }}&#xA;  uses: actions/setup-node@v2&#xA;  id: node-yarn&#xA;  with:&#xA;    node-version: &amp;quot;${{ env.NODE_VERSION }}&amp;quot;&#xA;    cache: yarn&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now one important consideration is that the reusable workflow will not inherit the parent workflow&amp;rsquo;s environment. This means secrets and environment variables need to be passed in via either &lt;code&gt;workflow_call.inputs&lt;/code&gt; or &lt;code&gt;workflow_call.secrets&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Annoyingly you can&amp;rsquo;t just set an input with &lt;code&gt;${{ env.FOO }}&lt;/code&gt; because the &lt;code&gt;env&lt;/code&gt; context object can&amp;rsquo;t be referenced. So if your reusable job is used a lot then you either have to hardcode the value as an &lt;code&gt;input&lt;/code&gt; to the reusable workflow or you store the environment variable as a secret in the GitHub UI so that you can reference it from the &lt;code&gt;workflow_call.secrets&lt;/code&gt; property.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There is so much more to explore with GitHub Actions. The bits I&amp;rsquo;ve mentioned here are just the tip of the iceberg. I strongly recommend you read the documentation and have a play around with these, and other features. Let me know on twitter what you think of GitHub Actions and whether you&amp;rsquo;re using it in your projects.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/github-actions/</guid>
      <link>https://www.integralist.co.uk/posts/github-actions/</link>
      <pubDate>Wed, 01 Dec 2021 00:00:00 +0000</pubDate>
      <title>GitHub Actions</title>
    </item>
    <item>
      <description>&lt;p&gt;I see a lot of posts on Vim &amp;lsquo;tips and tricks&amp;rsquo; and decided I&amp;rsquo;d have a go at putting together my own list of things that don&amp;rsquo;t typically see the light of day, but are super powerful and useful to know about.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;I want people to realise that they don&amp;rsquo;t need super complex Vim configurations with lots of third-party plugins, and this entire post is built on that motivation. This means you&amp;rsquo;ll find nearly everything described here is just plain Vim (no plugins). Don&amp;rsquo;t get me wrong, I use &lt;a href=&#34;https://github.com/Integralist/dotfiles/blob/master/.vimrc#L120-L142&#34; target=&#34;_blank&#34;&gt;a few plugins&lt;/a&gt;, but I try to keep them to a minimum and rely more on the fundamentals of how Vim works.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;[!NOTE]&#xA;Remember that &lt;code&gt;:help &amp;lt;some_phrase&amp;gt;&lt;/code&gt; is your friend! So if you don&amp;rsquo;t know about any features I mention (and I don&amp;rsquo;t explain them in this post), then use Vim&amp;rsquo;s help feature. You can also try &lt;a href=&#34;https://vimhelp.org/&#34; target=&#34;_blank&#34;&gt;https://vimhelp.org/&lt;/a&gt; too, which is a nice UI with autocomplete search box.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Let&amp;rsquo;s take a look at what we&amp;rsquo;ll be covering&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#using-vim-with-no-plugins&#34;&gt;Using Vim with no plugins&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#recording-repeatable-steps-with-macros&#34;&gt;Recording repeatable steps with macros&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#modifying-content-with-global-command&#34;&gt;Modifying content with &lt;code&gt;global&lt;/code&gt; command&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#substitutions-magic-regex-mode-and-other-flags&#34;&gt;Substitutions, magic regex mode and other flags&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#searching-and-filtering-content&#34;&gt;Searching and filtering content&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#processing-search-results-with-cdo-and-cfdo&#34;&gt;Processing search results with &lt;code&gt;cdo&lt;/code&gt; and &lt;code&gt;cfdo&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#filtering-quickfix-and-location-list-results&#34;&gt;Filtering quickfix and location list results&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#processing-files-with-tdo&#34;&gt;Processing files with &lt;code&gt;&amp;lt;T&amp;gt;do&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#automating-content-modification-using-ex-commands-from-the-shell&#34;&gt;Automating content modification using Ex commands from the shell&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#starting-vim-with-your-last-workspace&#34;&gt;Starting Vim with your last workspace&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#vims-start-up-process&#34;&gt;Vim&amp;rsquo;s start-up process&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#debugging-vim-issues&#34;&gt;Debugging Vim issues&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#autocomplete-with-no-plugins&#34;&gt;Autocomplete with no plugins&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#understanding-line-feed-and-carriage-returns&#34;&gt;Understanding line feed and carriage returns&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#auto-highlighting-keywords-and-creating-your-own-custom-highlighting&#34;&gt;Auto highlighting keywords (and creating your own custom highlighting)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#sorting-and-filtering-duplicates&#34;&gt;Sorting and filtering duplicates&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#miscellaneous-tips-and-tricks&#34;&gt;Miscellaneous tips and tricks&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;using-vim-with-no-plugins&#34;&gt;Using Vim with no plugins&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK we&amp;rsquo;re going to start super basic here and demonstrate a simple, but completely usable, Vim configuration which will keep &lt;em&gt;purists&lt;/em&gt; happy.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;set nocompatible number cursorline expandtab hlsearch visualbell tabstop=2 shiftwidth=2&#xA;syntax on&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;nocompatible&lt;/code&gt;: Stops odd issues †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;number&lt;/code&gt;: Turn on line numbers.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cursorline&lt;/code&gt;: Highlight the current line.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;expandtab&lt;/code&gt;: Convert tabs to spaces.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hlsearch&lt;/code&gt;: Highlight all search matches.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;visualbell&lt;/code&gt;: Stop Vim from beeping at you when you make a mistake.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tabstop&lt;/code&gt;: Set tab size in spaces (this is for manual indenting).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;shiftwidth&lt;/code&gt;: The number of spaces inserted for a tab (used for auto indenting).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;syntax on&lt;/code&gt;: Enable basic syntax highlighting.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† Example: Using arrow keys in INSERT mode will send key sequences that are misinterpreted by &lt;code&gt;vi&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;To try out this basic configuration use Vim&amp;rsquo;s &lt;a href=&#34;https://vimhelp.org/starting.txt.html#-u&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;-u&lt;/code&gt;&lt;/a&gt; flag. For example, you can start Vim with no configuration &lt;code&gt;vim -u NONE&lt;/code&gt; and then manually apply the configuration as shown above, or you can put it into a separate file and start Vim with that configuration instead of your normal one &lt;code&gt;vim -u ~/.vimrc-basic&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/vimbasic.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/vimbasic.png&#34; alt=&#34;vimbasic&#34; /&gt;&lt;/a&gt;&#xA;&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above screenshot you can see I&amp;rsquo;m just using the basic configuration (looks quite nice) along with a couple of split buffer windows (&lt;a href=&#34;https://vimhelp.org/windows.txt.html#%3Avs&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:vs&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m also a big user of Vim&amp;rsquo;s built-in tabs feature &lt;a href=&#34;https://vimhelp.org/tabpage.txt.html#%3Atabnew&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:tabnew&lt;/code&gt;&lt;/a&gt; (not shown in the screenshot) and also &lt;a href=&#34;https://vimhelp.org/editing.txt.html#%3Alcd&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:lcd&lt;/code&gt;&lt;/a&gt; for changing each tab&amp;rsquo;s root location (which allows me to easily switch between multiple projects).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the screen shot you can see I&amp;rsquo;m also using &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Avimgrep&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:vimgrep&lt;/code&gt;&lt;/a&gt; to search for code in my current project (e.g. &lt;code&gt;:vimgrep /func/j **/*&lt;/code&gt; followed with &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Acopen&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:copen&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although not shown in the screenshot I also use the built-in file/directory explorer, AKA &amp;lsquo;netrw&amp;rsquo;, by executing &lt;a href=&#34;https://vimhelp.org/pi_netrw.txt.html#%3AExplore&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:Ex&lt;/code&gt;&lt;/a&gt;. This let&amp;rsquo;s me manually traverse the current project directory (see also &lt;a href=&#34;https://vimhelp.org/pi_netrw.txt.html#%3AVexplore&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:Vex&lt;/code&gt;&lt;/a&gt; for vertical split and &lt;a href=&#34;https://vimhelp.org/pi_netrw.txt.html#%3ASexplore&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:Sex&lt;/code&gt;&lt;/a&gt;, no sniggering at the back, for a horizontal split). When using netrw I like to configure it to ignore certain files, which you can do like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;&amp;quot; don&#39;t display .swp files&#xA;let g:netrw_list_hide= &#39;.*\.swp$,.*\.DS_Store&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As mentioned earlier, using &lt;code&gt;:h&lt;/code&gt; is a great way to learn about native features. As an example, I only recently discovered &lt;code&gt;:cq&lt;/code&gt; which quits Vim without writing to any files &lt;em&gt;and&lt;/em&gt; it will return an error exit code (this is useful in scenarios like writing &lt;code&gt;git&lt;/code&gt; commit messages where you want to bail out at the last minute).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another core feature of Vim I like to use is &lt;a href=&#34;https://vimhelp.org/motion.txt.html#%3Amarks&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:marks&lt;/code&gt;&lt;/a&gt; which is a bookmark feature (see &lt;a href=&#34;https://vimhelp.org/usr_03.txt.html#bookmark&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h bookmark&lt;/code&gt;&lt;/a&gt; for more details). This can be useful for jumping around multiple locations within a single large file. The cool thing about marks is that they are unique to each file, so I tend to create marks using the registers a, b, c &amp;hellip;etc as it&amp;rsquo;s easier to remember, and then I can use those same registers in each file (meaning I don&amp;rsquo;t have to jump to another file and be like &amp;ldquo;oh was I using d, e, f in this file or a, b, c?).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As well as using &lt;a href=&#34;https://vimhelp.org/change.txt.html#%21&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;!&lt;/code&gt;&lt;/a&gt; which lets me filter content through an external program. So for example, if I have the following lines&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo&#xA;foobar&#xA;baz&#xA;quxfoo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;and I want to filter out any lines that contains &lt;code&gt;foo&lt;/code&gt;, then I can visually select those lines and pass the selection through to my shell&amp;rsquo;s &lt;code&gt;grep&lt;/code&gt; command like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:&#39;&amp;lt;,&#39;&amp;gt;!grep -v foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would result in those lines being replaced with the single line containing &lt;code&gt;baz&lt;/code&gt;, as all the other lines were containing &lt;code&gt;foo&lt;/code&gt;. Now a more Vim idiomatic approach to this particular problem is demonstrated in the section &amp;ldquo;&lt;a href=&#34;#modifying-content-with-global-command&#34;&gt;Modifying content with &lt;code&gt;global&lt;/code&gt; command&lt;/a&gt;&amp;rdquo;, but the takeaway is that the &lt;code&gt;!&lt;/code&gt; command is awesome.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now a more practical example of using &lt;code&gt;!&lt;/code&gt; might be to take a single line of JSON and pipe it into a tool that pretty prints the data (the following example uses the &lt;code&gt;%&lt;/code&gt; range to send the whole buffer to the program):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%!python -m json.tool&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you use &lt;a href=&#34;https://stedolan.github.io/jq/&#34; target=&#34;_blank&#34;&gt;jq&lt;/a&gt; you can both prettify &lt;code&gt;%!jq&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; minify &lt;code&gt;%!jq -c&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Or if you didn&amp;rsquo;t want to replace the current buffer, but instead &lt;em&gt;append&lt;/em&gt; a pretty printed version on the line(s) after the current line, then you would use &lt;code&gt;:read&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:read !cat % | python -m json.tool&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Want to populate the Vim quickfix list with output from some shell command? No problem: Vim already supports &lt;code&gt;make&lt;/code&gt; by default so that &lt;code&gt;:make &amp;lt;target&amp;gt;&lt;/code&gt; will execute the specified Makefile target for you (you&amp;rsquo;ll need to manually open the quickfix window &lt;code&gt;:copen&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you can also change the default program using &lt;code&gt;set makeprg=&amp;lt;whatever&amp;gt;&lt;/code&gt;! Now you can pass your current buffer to it using &lt;code&gt;:make %&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also do clever things like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;autocmd BufWritePost *.go :cex system(&#39;revive &#39;..expand(&#39;%:p&#39;)) | copen&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;which executes a command (in this case &lt;code&gt;revive&lt;/code&gt;, a golang code linter) and passes it the current file path, and opens the results up in the quickfix window!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And the great thing about all of this is that there are &lt;em&gt;no&lt;/em&gt; plugins required. It&amp;rsquo;s all standard Vim features. You just need to know they exist.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you do decide to use plugins, then don&amp;rsquo;t forget to &lt;code&gt;vim -c &amp;quot;:helptags ALL&amp;quot; -c &amp;quot;:q&amp;quot;&lt;/code&gt; to ensure you get all the relevant help information loaded.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now, there may be times where you want a minimal config but with some extra treats, I&amp;rsquo;ll typically have a &lt;code&gt;~/.vimrc-core&lt;/code&gt; file with the following configuration that gives me the above &amp;lsquo;basic&amp;rsquo; configuration (with some other configuration which isn&amp;rsquo;t essential but also isn&amp;rsquo;t superfluous either) along with some &lt;em&gt;core&lt;/em&gt; plugins I like to use):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;set nocompatible number autoread cursorline expandtab hlsearch visualbell &#xA;set tabstop=2 shiftwidth=2 clipboard+=unnamed wildmenu hidden noswapfile&#xA;syntax on&#xA;packadd cfilter&#xA;&#xA;call plug#begin(&#39;~/.vim/plugged&#39;)&#xA;Plug &#39;junegunn/fzf&#39;, { &#39;do&#39;: { -&amp;gt; fzf#install() } }&#xA;Plug &#39;junegunn/fzf.vim&#39; &amp;quot; &amp;lt;Tab&amp;gt; to select multiple results&#xA;Plug &#39;mileszs/ack.vim&#39;&#xA;Plug &#39;unblevable/quick-scope&#39;&#xA;call plug#end()&#xA;&#xA;map &amp;lt;leader&amp;gt;f :FZF&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;b :Buffers!&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;g :GFiles?&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;w :Windows&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;l :Lines&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;t :AgC&amp;lt;CR&amp;gt;&#xA;&#xA;set wildignore+=*/.git/*,*/node_modules/*,*/.hg/*,*/.svn/*.,*/.DS_Store&#xA;set wildmode=list:longest,list:full&#xA;&#xA;autocmd VimEnter * command! -nargs=* -bang AgC \&#xA;call fzf#vim#ag(&#xA;      \ &amp;lt;q-args&amp;gt;, &#xA;      \ &#39;--path-to-ignore ~/.ignore &#39;&#xA;      \ . &#39;--hidden &#39;&#xA;      \ . &#39;--ignore &amp;quot;node_modules&amp;quot; &#39;&#xA;      \ . &#39;--ignore-dir=&amp;quot;vendor&amp;quot; &#39;&#xA;      \ . &#39;--skip-vcs-ignores&#39;, &#xA;      \ &amp;lt;bang&amp;gt;0&#xA;      \)&#xA;&#xA;let g:ackprg = &#39;ag --vimgrep --smart-case &#39;&#xA;      \ . &#39;--path-to-ignore ~/.ignore &#39;&#xA;      \ . &#39;--hidden &#39;&#xA;      \ . &#39;--ignore-dir=node_modules &#39;&#xA;      \ . &#39;--ignore-dir=vendor &#39;&#xA;      \ . &#39;--skip-vcs-ignores&#39;&#xA;&#xA;let g:ack_mappings = {&#xA;  \ &amp;quot;h&amp;quot;: &amp;quot;&amp;lt;C-W&amp;gt;&amp;lt;CR&amp;gt;:exe &#39;wincmd &#39; (&amp;amp;splitbelow ? &#39;J&#39; : &#39;K&#39;)&amp;lt;CR&amp;gt;&amp;lt;C-W&amp;gt;p&amp;lt;C-W&amp;gt;J&amp;lt;C-W&amp;gt;p&amp;quot;,&#xA;  \ &amp;quot;v&amp;quot;: &amp;quot;&amp;lt;C-W&amp;gt;&amp;lt;CR&amp;gt;:exe &#39;wincmd &#39; (&amp;amp;splitright ? &#39;L&#39; : &#39;H&#39;)&amp;lt;CR&amp;gt;&amp;lt;C-W&amp;gt;p&amp;lt;C-W&amp;gt;J&amp;lt;C-W&amp;gt;p&amp;quot;}&#xA;  &#xA;silent! tnoremap &amp;lt;Esc&amp;gt; &amp;lt;C-\&amp;gt;&amp;lt;C-n&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Yes it&amp;rsquo;s bigger than the &amp;lsquo;basic&amp;rsquo; version, but remember this is still only 30 lines of configuration and it gives me a much richer experience. Again, the motivation for this post is about &lt;em&gt;not&lt;/em&gt; needing plugins, and you should aim for understanding the fundamentals of Vim, but this gives you a little bit of both worlds 😉&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;recording-repeatable-steps-with-macros&#34;&gt;Recording repeatable steps with macros&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Vim allows you to &lt;a href=&#34;https://vimhelp.org/repeat.txt.html#recording&#34; target=&#34;_blank&#34;&gt;record&lt;/a&gt; any typed characters so that you can then replay them again. This makes applying a set of complex changes multiple times across a code base much easier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The workflow is actually really simple&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Press &lt;code&gt;q&lt;/code&gt; followed by any valid &lt;a href=&#34;https://vimhelp.org/change.txt.html#registers&#34; target=&#34;_blank&#34;&gt;register&lt;/a&gt; to start recording (you should see something like &lt;code&gt;recording @&amp;lt;register&amp;gt;&lt;/code&gt; in the status bar).&lt;/li&gt;&#xA;&lt;li&gt;Start typing the changes you need to make.&lt;/li&gt;&#xA;&lt;li&gt;Press &lt;code&gt;q&lt;/code&gt; again to stop recording.&lt;/li&gt;&#xA;&lt;li&gt;Press &lt;code&gt;@&amp;lt;register&amp;gt;&lt;/code&gt; to replay the recorded steps.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;I typically use the &lt;code&gt;q&lt;/code&gt; register as it&amp;rsquo;s the quickest way to start recording a macro, as my finger already has to be over the &lt;code&gt;q&lt;/code&gt; key to start recording any way (e.g. &lt;code&gt;qq&lt;/code&gt; to record into &lt;code&gt;q&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now you might be wondering what happens if your steps need to include the &lt;code&gt;q&lt;/code&gt; character (if that character is what stops a macro recording). Well luckily &lt;code&gt;q&lt;/code&gt; only triggers the macro to stop recording if it&amp;rsquo;s the first character pressed as part of a new operation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to demonstrate, if I want a macro that deletes all occurrences of the letter &lt;code&gt;q&lt;/code&gt; from the current line, then I would type the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;qq0V:s/q//g&amp;lt;Enter&amp;gt;q&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s break these steps down&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;qq&lt;/code&gt;: record into the &lt;code&gt;q&lt;/code&gt; register.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;0&lt;/code&gt;: move to the start of the line.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;V&lt;/code&gt;: select the entire line.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;:&lt;/code&gt;: start Ex mode&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;s/q//g&lt;/code&gt;: a substitution that deletes &lt;code&gt;q&lt;/code&gt; &amp;lsquo;globally&amp;rsquo; (i.e. multiple times)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt;: I press the Enter key to have the substitution applied to the current line.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;q&lt;/code&gt;: I stop recording.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you execute &lt;code&gt;:reg&lt;/code&gt; you&amp;rsquo;ll see the &lt;code&gt;q&lt;/code&gt; register contains something very similar&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0V:s/q//g^M&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Once you&amp;rsquo;ve replayed a macro (e.g. &lt;code&gt;@q&lt;/code&gt;) you can trigger it again without having to specify the register by typing &lt;code&gt;@&lt;/code&gt; again, e.g. &lt;code&gt;@@&lt;/code&gt; will rerun the last used macro.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you need to run a macro a certain number of times then just prefix it with that number. For example, to run a macro six times I&amp;rsquo;d type &lt;code&gt;6@&amp;lt;register&amp;gt;&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;modifying-content-with-global-command&#34;&gt;Modifying content with &lt;code&gt;global&lt;/code&gt; command&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are times when you want to execute an &lt;a href=&#34;https://vimhelp.org/cmdline.txt.html#%3A&#34; target=&#34;_blank&#34;&gt;Ex&lt;/a&gt; command for any lines that match a specific pattern. That is where the &lt;a href=&#34;hhttps://vimhelp.org/intro.txt.html#Exttps://vimhelp.org/repeat.txt.html#%3Aglobal&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:global&lt;/code&gt;&lt;/a&gt; comes in handy (this is different to &lt;a href=&#34;https://vimhelp.org/change.txt.html#%3As&#34; target=&#34;_blank&#34;&gt;substitution&lt;/a&gt;, which we&amp;rsquo;ll look at after).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a file with the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo&#xA;foobar&#xA;barfoo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You want to delete any lines that start with &lt;code&gt;foo&lt;/code&gt;. To do that using the global command, would look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:g/^foo/d&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you just want to see what would match, you could either use the &lt;a href=&#34;https://vimhelp.org/various.txt.html#%3Ap&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:p&lt;/code&gt;&lt;/a&gt; command (e.g. &lt;code&gt;:g/^foo/p&lt;/code&gt;) or just leave off the command altogether as &lt;code&gt;:p&lt;/code&gt; is the default behaviour.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s cool about the &lt;code&gt;:global&lt;/code&gt; command is that because the command can be &lt;em&gt;any&lt;/em&gt; Ex command, it means you can also use &lt;a href=&#34;https://vimhelp.org/repeat.txt.html#recording&#34; target=&#34;_blank&#34;&gt;macros&lt;/a&gt; by way of the &lt;a href=&#34;https://vimhelp.org/various.txt.html#%3Anorm&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:norm&lt;/code&gt;&lt;/a&gt; command. In the following example we search for &lt;code&gt;foo&lt;/code&gt; anywhere in the content and then apply the &lt;code&gt;@q&lt;/code&gt; register to the matches&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:g/foo/norm @q | update &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With &lt;code&gt;:norm&lt;/code&gt; it also means the first example could be mimicked with it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;# both are the same&#xA;:g/^foo/d&#xA;:g/^foo/norm dd&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now want if you needed to use controls keys like &lt;code&gt;&amp;lt;Shift&amp;gt;&lt;/code&gt;? Well, you can do that with the &lt;code&gt;:global&lt;/code&gt; command too, but this time the command to be called would be the &lt;a href=&#34;https://vimhelp.org/eval.txt.html#%3Aexecute&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:execute&lt;/code&gt;&lt;/a&gt; command. The &lt;code&gt;:execute&lt;/code&gt; command will enable you to provide a string that will be evaluated into an Ex command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So imagine you had a file like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo&#xA;bar&#xA;baz&#xA;qux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And you wanted it to be like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo bar&#xA;baz qux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then you would use the following (note that &lt;code&gt;&amp;lt;Shift-j&amp;gt;&lt;/code&gt; in normal mode causes the following line to be joined to the current line):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:g/^/exe &amp;quot;norm \&amp;lt;s-j&amp;gt;&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also use the &lt;code&gt;!&lt;/code&gt; to cause &lt;code&gt;:global&lt;/code&gt; to behave in the reverse (i.e. anything that &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; match the given pattern, apply the command to).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;substitutions-magic-regex-mode-and-other-flags&#34;&gt;Substitutions, magic regex mode and other flags&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most people know how to use Vim&amp;rsquo;s &lt;a href=&#34;https://vimhelp.org/change.txt.html#%3Asubstitute&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:substitute&lt;/code&gt;&lt;/a&gt; command, but it seems people are less familiar with the use of &lt;a href=&#34;https://vimhelp.org/pattern.txt.html#%2F%5Cv&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;\v&lt;/code&gt;&lt;/a&gt; as a way to enable &amp;lsquo;magic mode&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me &amp;lsquo;magic mode&amp;rsquo; really just means my regex pattern doesn&amp;rsquo;t require escaping characters like &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;()&lt;/code&gt; which is quite frustrating. I just prefix my pattern with &lt;code&gt;\v&lt;/code&gt; and I can forget that for the most part (†). more like I&amp;rsquo;d expect it to from an engine supporting &lt;a href=&#34;https://www.pcre.org/&#34; target=&#34;_blank&#34;&gt;PCRE&lt;/a&gt; (Perl Compatible Regular Expressions, probably the most common implementation).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† One caveat when using magic mode is that you &lt;em&gt;do&lt;/em&gt; need to escape curly brackets as most regex engines treat &lt;code&gt;{}&lt;/code&gt; as a &amp;lsquo;quantifier&amp;rsquo; such as &lt;code&gt;{1,3}&lt;/code&gt; and so if I&amp;rsquo;m programming/coding and I need to search for a &lt;code&gt;{&lt;/code&gt; (which is common in programming languages), then I have to escape it &lt;code&gt;\{&lt;/code&gt;. You can learn more about Vim&amp;rsquo;s regex engine via the help but also via &lt;a href=&#34;http://vimregex.com/&#34; target=&#34;_blank&#34;&gt;vimregex.com&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start off by looking at &lt;code&gt;\v&lt;/code&gt; not using a substitution but with a standard &lt;a href=&#34;https://vimhelp.org/pattern.txt.html#%2F&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;/&lt;/code&gt;&lt;/a&gt; search.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine we have a project that instruments logging with different levels throughout. In this scenario imagine we have three log levels: debug, error and info that are used multiple times across the project. The log calls look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;log(&#39;foo&#39;, level=&#39;debug&#39;)&#xA;log(&#39;bar&#39;, level=&#39;error&#39;)&#xA;log(&#39;baz&#39;, level=&#39;info&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Lastly, imagine we want to find every instance of a log call but only those that are of the &amp;lsquo;debug&amp;rsquo; and &amp;lsquo;error&amp;rsquo; level, we &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; want to get any results for an &amp;lsquo;info&amp;rsquo; level log call.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this we need a &lt;a href=&#34;https://www.regular-expressions.info/lookaround.html&#34; target=&#34;_blank&#34;&gt;lookaround assertion&lt;/a&gt;. For our purposes we&amp;rsquo;re going to use a lookaround ahead (specifically a &lt;em&gt;negative&lt;/em&gt; lookahead). The way a negative lookahead assertion works is that you provide a pattern you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; want to be matched.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For our use case, if using a normal PCRE engine, could look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;level=&#39;(?!info)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In Vim this translates to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;level=&#39;\(info\)\@!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or if you&amp;rsquo;re using &amp;lsquo;magic mode&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;\vlevel\=&#39;(info)@!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice with magic mode we don&amp;rsquo;t have to escape a bunch of things like the capture groups (i.e. the parenthesis) or the &lt;code&gt;@&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If the number of permutations was small enough, then it&amp;rsquo;s arguably simpler to use an alternator pipe like &lt;code&gt;/\vlevel\=&#39;(debug|error)&lt;/code&gt; because remembering the lookaround syntax like &lt;code&gt;@!&lt;/code&gt; (and its friends) might be hard to recall.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next we&amp;rsquo;ll look at &lt;code&gt;\u&lt;/code&gt; and &lt;code&gt;\U&lt;/code&gt; (they have lowercase equivalents: &lt;code&gt;\l&lt;/code&gt; and &lt;code&gt;\L&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember our example log instrumentation calls from earlier, imagine we need to make the word &lt;code&gt;level&lt;/code&gt; capitalised. Here&amp;rsquo;s how we could achieve that (note: I&amp;rsquo;ll show a better way after) using substitutions with magic mode and the &lt;code&gt;\u&lt;/code&gt; special flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%s/\v(l)(evel)/\u\1\2/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this example we&amp;rsquo;ve used the &lt;code&gt;%&lt;/code&gt; range to represent the entire content buffer, and we&amp;rsquo;ve used two capturing groups, one around the letter &lt;code&gt;l&lt;/code&gt; and another capture group around the remainder of the word. In the replacement section we use &lt;code&gt;\u&lt;/code&gt; to trigger an uppercase on the capture group &lt;code&gt;\1&lt;/code&gt; and then we print out the second capture group &lt;code&gt;\2&lt;/code&gt; following it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now this is actually more work than it needs to be because no matter what you capture, &lt;code&gt;\u&lt;/code&gt; will only ever uppercase the &lt;em&gt;first&lt;/em&gt; character, so we only really need a single capture group:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%s/\v(level)/\u\1/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But what about the &lt;code&gt;\U&lt;/code&gt; equivalent? That will uppercase everything that follows, so if we needed the word &lt;code&gt;level&lt;/code&gt; to be &lt;code&gt;LEVEL&lt;/code&gt; then that&amp;rsquo;s exactly what we&amp;rsquo;d need to use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%s/\v(level)/\U\1/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You could also use &lt;code&gt;\U&lt;/code&gt; for uppercasing just the first letter, but you&amp;rsquo;d need to use either &lt;code&gt;\e&lt;/code&gt; or &lt;code&gt;\E&lt;/code&gt; (as a terminator) along with the two capture group design we had originally, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%s/\v(l)(evel)/\U\1\e\2/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;For more details refer to &lt;a href=&#34;https://vimhelp.org/change.txt.html#sub-replace-special&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h sub-replace-special&lt;/code&gt;&lt;/a&gt;, but also &lt;a href=&#34;https://vimhelp.org/pattern.txt.html#whitespace&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h whitespace&lt;/code&gt;&lt;/a&gt; which elaborates on some other special regex pattern flags.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;searching-and-filtering-content&#34;&gt;Searching and filtering content&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following are native Vim solutions to finding files (and also searching multiple files for specific content).&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#finding-a-single-file&#34;&gt;Finding a single file&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#finding-content-within-one-or-more-files&#34;&gt;Finding content within one or more files&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#using-external-shell-tool&#34;&gt;Using external shell tool&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#search-plugins&#34;&gt;Search plugins&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;finding-a-single-file&#34;&gt;Finding a single file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To find a &lt;em&gt;single&lt;/em&gt; file you can use the &lt;code&gt;:find&lt;/code&gt; Ex command and pass it a wildcard glob character to help search recursively for the specified file pattern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Example: we want to find a file called &lt;code&gt;next.config.js&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:find **/next.*.js &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;We could have just done &lt;code&gt;**/next.config.js&lt;/code&gt; but in case you weren&amp;rsquo;t familiar with the filename, then using another wildcard like we did helps to narrow things down.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;finding-content-within-one-or-more-files&#34;&gt;Finding content within one or more files&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You have two options for locating a string within a file (or multiple files) and that&amp;rsquo;s the following Ex commands&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;:vimgrep&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;:lvimgrep&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The difference is that &lt;code&gt;lvimgrep&lt;/code&gt; opens the results in a &amp;lsquo;location&amp;rsquo; window and every open split window can have its own location window, while &lt;code&gt;vimgrep&lt;/code&gt; opens the results in a &amp;lsquo;quickfix&amp;rsquo; window and there can only be one of those shown.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning if you ran &lt;code&gt;vimgrep&lt;/code&gt; in one split window and then ran it again (e.g. you&amp;rsquo;re looking for something different now) from another window, then your first set of results would be replaced with the latter results. If you instead used &lt;code&gt;lvimgrep&lt;/code&gt; then you could have multiple search results displayed (one for each split window).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the basic syntax structure:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:vimgrep  /&amp;lt;searchTerm&amp;gt;/[gj] &amp;lt;/path/to/project/**/*.go&amp;gt;&#xA;:lvimgrep /&amp;lt;searchTerm&amp;gt;/[gj] &amp;lt;/path/to/project/*&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;j&lt;/code&gt; prevents Vim from trying to open the first file match (also, if you don&amp;rsquo;t use &lt;code&gt;j&lt;/code&gt; then the location list won&amp;rsquo;t be populated with results as it&amp;rsquo;ll presume the first match was all you wanted), while &lt;code&gt;g&lt;/code&gt; means &amp;ldquo;ensure every match on a single line is displayed&amp;rdquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Example usage (we&amp;rsquo;re searching for any reference to &lt;code&gt;class&lt;/code&gt; anywhere in the project):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:vimgrep /class/gj **/*&#xA;:copen&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For anyone unfamiliar, the &lt;code&gt;copen&lt;/code&gt; command will open Vim&amp;rsquo;s &amp;lsquo;quickfix&amp;rsquo; window, while the &lt;code&gt;lopen&lt;/code&gt; command will open the &amp;lsquo;location list&amp;rsquo; (refer to &lt;code&gt;:h copen&lt;/code&gt; and &lt;code&gt;:h lopen&lt;/code&gt; to find related commands).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a nice trick if you&amp;rsquo;re using the &lt;em&gt;append&lt;/em&gt; version of &lt;code&gt;vimgrep&lt;/code&gt; (i.e. &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Avimgrepa&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;vimgrepa&lt;/code&gt;&lt;/a&gt;), is if you make a mistake populating the quickfix window, then you can use &lt;code&gt;:cex []&lt;/code&gt; to clear it! See &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Acex&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:cex&lt;/code&gt;&lt;/a&gt; for details.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;One interesting feature of &lt;code&gt;:vimgrep&lt;/code&gt; is that you can use the result of a backtick expression to be the file source:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:vimgrep /ssh/j `find . -type f -name &#39;tmux*&#39;`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also use a prior &lt;code&gt;/&lt;/code&gt; search pattern like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:vimgrep /&amp;lt;C-r&amp;gt;// *&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To clarify the above command, imagine you have a complex pattern you want to play around with and test with a single file so you use &lt;code&gt;/&lt;/code&gt; to get Vim to jump into search mode for the current buffer content and then type in your complex pattern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once happy with your pattern, you now want to use it again for multiple files but you don&amp;rsquo;t want to have to type the pattern out again (especially in case it&amp;rsquo;s complex enough to easily include an unexpected typo).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So you type &lt;code&gt;:vimgrep /&lt;/code&gt; and after that is where you would typically start typing your search pattern, at this point press &lt;code&gt;&amp;lt;Ctrl-r&amp;gt;&lt;/code&gt; followed by &lt;code&gt;/&lt;/code&gt; and Vim will automatically insert the last search pattern for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine &lt;code&gt;...&lt;/code&gt; was the last search pattern, this would mean the Ex mode command would currently look like &lt;code&gt;:vimgrep /...&lt;/code&gt; so you would need to finish the command &lt;code&gt;/ *&lt;/code&gt; (so it&amp;rsquo;s almost like you wrote the command in its entirety).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you use another plugin like &lt;code&gt;:Ack!&lt;/code&gt; then &lt;code&gt;&amp;lt;C-r&amp;gt;/&lt;/code&gt; works to insert the last search pattern still (e.g. &lt;code&gt;:Ack! &#39;&amp;lt;C-r&amp;gt;/&#39;&lt;/code&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;using-external-shell-tool&#34;&gt;Using external shell tool&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;:vimgrep&lt;/code&gt; and &lt;code&gt;:lvimgrep&lt;/code&gt; commands use an internal Vim search implementation. Which might not be as performant as using a separate/external search tool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why Vim also provides a &lt;code&gt;:grep&lt;/code&gt; command, which allows you to utilise an &lt;em&gt;external&lt;/em&gt; search program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The default program it uses can be seen by running:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:set grepprg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which should return something like the following (which is the system provided &lt;code&gt;grep&lt;/code&gt; tool):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;grepprg=grep -n $* /dev/null&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I have mine set to use &lt;code&gt;ag&lt;/code&gt; (i.e. the &lt;a href=&#34;https://github.com/ggreer/the_silver_searcher&#34; target=&#34;_blank&#34;&gt;Silver Searcher&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;set grepprg=ag\ --nogroup\ --nocolor\ --skip-vcs-ignores&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;spaces have to be escaped with a backslash &lt;code&gt;\&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You can now use the new program like so (e.g. to find any reference to the word &lt;code&gt;class&lt;/code&gt; using the Silver Searcher tool):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:grep class&#xA;:copen&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you still need to open the &amp;lsquo;quickfix&amp;rsquo; window manually afterwards to see the results.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;All this said, you can improve the performance of &lt;code&gt;:vimgrep&lt;/code&gt; by prefixing it with &lt;a href=&#34;https://vimhelp.org/autocmd.txt.html#%3Anoautocmd&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:noautocmd&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:noautocmd vimgrep /{pattern}/[flags] {file(s)}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is because &lt;code&gt;:vimgrep&lt;/code&gt; uses Vim&amp;rsquo;s procedures to read files, which can involve execution of several autocommands. So this disables autocommands.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;search-plugins&#34;&gt;Search plugins&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, the built-in tools are great and flexible, but I&amp;rsquo;ll be honest with you and say that in my day-to-day Vim usage you&amp;rsquo;ll find me using &lt;a href=&#34;https://github.com/junegunn/fzf.vim&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:FZF&lt;/code&gt;&lt;/a&gt; to find files and &lt;a href=&#34;https://github.com/mileszs/ack.vim&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:Ack! &#39;&amp;lt;regex&amp;gt;&#39; &amp;lt;path&amp;gt;&lt;/code&gt;&lt;/a&gt; to find files that contain a particular string.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Although I use the &lt;a href=&#34;https://github.com/mileszs/ack.vim&#34; target=&#34;_blank&#34;&gt;Ack&lt;/a&gt; Vim plugin, I actually configure it to use the &lt;code&gt;ag&lt;/code&gt; &amp;lsquo;&lt;a href=&#34;https://github.com/ggreer/the_silver_searcher&#34; target=&#34;_blank&#34;&gt;Silver Searcher&lt;/a&gt;&amp;rsquo; shell command.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;&amp;quot; Plugin Managment&#xA;&amp;quot; https://github.com/junegunn/vim-plug#example&#xA;&amp;quot;&#xA;&amp;quot; Reload .vimrc and :PlugInstall to install plugins.&#xA;&amp;quot; Use single quotes as requested by vim-plug.&#xA;&amp;quot;&#xA;&amp;quot; Specify a directory for plugins&#xA;call plug#begin(&#39;~/.vim/plugged&#39;)&#xA;&#xA;Plug &#39;junegunn/fzf&#39;, { &#39;do&#39;: { -&amp;gt; fzf#install() } }&#xA;Plug &#39;junegunn/fzf.vim&#39; &amp;quot; &amp;lt;Tab&amp;gt; to select multiple results&#xA;Plug &#39;mileszs/ack.vim&#39;&#xA;&#xA;&amp;quot; Initialize plugin system&#xA;call plug#end()&#xA;&#xA;&amp;quot; PLUGIN CONFIGURATION...&#xA;&#xA;&amp;quot; FZF (search files)&#xA;&amp;quot;&#xA;&amp;quot; Shift-Tab to select multiple files&#xA;&amp;quot;&#xA;&amp;quot; Ctrl-t = tab&#xA;&amp;quot; Ctrl-x = split&#xA;&amp;quot; Ctrl-v = vertical&#xA;&amp;quot;&#xA;&amp;quot; We also set FZF_DEFAULT_COMMAND in ~/.bashrc&#xA;&amp;quot; Also we use --ignore-dir multiple times there&#xA;&amp;quot; Using --hidden to allow searching hidden directories like .github&#xA;&amp;quot; The --hidden still respects .ignore where we ignore things like .git&#xA;&amp;quot; NOTE: you need --path-to-ignore ~/.ignore otherwise ag only uses local ignore ./.ignore&#xA;&amp;quot;&#xA;&amp;quot; Note use :map command to see current mappings (also :vmap, :nmap, :omap).&#xA;&amp;quot; Can also restrict to specific mapping `:map &amp;lt;Leader&amp;gt;w`&#xA;&amp;quot; https://vi.stackexchange.com/questions/7722/how-to-debug-a-mapping&#xA;map &amp;lt;leader&amp;gt;f :FZF!&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;b :Buffers!&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;g :GFiles!?&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;w :Windows!&amp;lt;CR&amp;gt;&#xA;map &amp;lt;leader&amp;gt;t :AgC!&amp;lt;CR&amp;gt;&#xA;&#xA;&amp;quot; Files matched are ignored when expanding wildcards&#xA;set wildignore+=*/.git/*,*/node_modules/*,*/.hg/*,*/.svn/*.,*/.DS_Store &#xA;set wildmode=list:longest,list:full&#xA;&#xA;&amp;quot; configure FZF text search command to have default flags included&#xA;autocmd VimEnter * command! -nargs=* -bang AgC call fzf#vim#ag(&#xA;      \ &amp;lt;q-args&amp;gt;, &#xA;      \ &#39;--path-to-ignore ~/.ignore &#39;&#xA;      \ . &#39;--hidden &#39;&#xA;      \ . &#39;--ignore &amp;quot;node_modules&amp;quot; &#39;&#xA;      \ . &#39;--ignore-dir=&amp;quot;vendor&amp;quot; &#39;&#xA;      \ . &#39;--skip-vcs-ignores&#39;, &#xA;      \ &amp;lt;bang&amp;gt;0&#xA;      \)&#xA;&#xA;&amp;quot; ack&#xA;let g:ackprg = &#39;ag --vimgrep --smart-case --path-to-ignore ~/.ignore \&#xA;--hidden --ignore-dir=node_modules --ignore-dir=vendor --skip-vcs-ignores&#39;&#xA;&#xA;&amp;quot; help Ack mappings to respect my split settings&#xA;let g:ack_mappings = {&#xA;  \ &amp;quot;h&amp;quot;: &amp;quot;&amp;lt;C-W&amp;gt;&amp;lt;CR&amp;gt;:exe &#39;wincmd &#39; (&amp;amp;splitbelow ? &#39;J&#39; : &#39;K&#39;)&amp;lt;CR&amp;gt;&amp;lt;C-W&amp;gt;p&amp;lt;C-W&amp;gt;J&amp;lt;C-W&amp;gt;p&amp;quot;,&#xA;  \ &amp;quot;v&amp;quot;: &amp;quot;&amp;lt;C-W&amp;gt;&amp;lt;CR&amp;gt;:exe &#39;wincmd &#39; (&amp;amp;splitright ? &#39;L&#39; : &#39;H&#39;)&amp;lt;CR&amp;gt;&amp;lt;C-W&amp;gt;p&amp;lt;C-W&amp;gt;J&amp;lt;C-W&amp;gt;p&amp;quot;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now it&amp;rsquo;s probably worth me quickly mentioning that there are two &lt;em&gt;small&lt;/em&gt; plugins I really like that&amp;rsquo;s related to this section:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/google/vim-searchindex&#34; target=&#34;_blank&#34;&gt;vim-searchindex&lt;/a&gt; which shows how many times a search pattern, such as &lt;code&gt;/your_pattern&lt;/code&gt;, occurs in the current buffer. After each search, it displays total number of matches, as well as the index of a current match.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/unblevable/quick-scope&#34; target=&#34;_blank&#34;&gt;quick-scope&lt;/a&gt; which highlights a unique character in every word on a line to help you more efficiently jump around on a single line using the standard &lt;code&gt;f&lt;/code&gt;, &lt;code&gt;F&lt;/code&gt;, &lt;code&gt;t&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt; motions.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;processing-search-results-with-cdo-and-cfdo&#34;&gt;Processing search results with &lt;code&gt;cdo&lt;/code&gt; and &lt;code&gt;cfdo&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So you&amp;rsquo;ve run a search using something like &lt;code&gt;:vimgrep&lt;/code&gt; or &lt;code&gt;:grep&lt;/code&gt; or maybe a plugin like &lt;code&gt;:Ack&lt;/code&gt;, and you&amp;rsquo;ve populated a &amp;lsquo;quickfix&amp;rsquo; window (or maybe a &amp;lsquo;location list&amp;rsquo; if using something like &lt;code&gt;:lvimgrep&lt;/code&gt;) with search results. Now you want to apply some sort of change to each search result.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where the &lt;code&gt;&amp;lt;c|l&amp;gt;[f]do&lt;/code&gt; commands come in handy:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;quickfix:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cdo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cfdo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;location list:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ldo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;lfdo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The first thing you need to think about is whether you want your &amp;lsquo;action&amp;rsquo; to be applied to each &amp;lsquo;entry&amp;rsquo; in the list or to each &amp;lsquo;file&amp;rsquo; in the list. Think about the list of results you have&amp;hellip; depending on what you searched for it&amp;rsquo;s possible you&amp;rsquo;ll see the same file appear multiple times because there were multiple entries found within the file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So commands like &lt;code&gt;cdo&lt;/code&gt; and &lt;code&gt;ldo&lt;/code&gt; will operate on each entry, while &lt;code&gt;cfdo&lt;/code&gt; and &lt;code&gt;lfdo&lt;/code&gt; will only operate on each file. Meaning if a file appears 10 times, then you&amp;rsquo;ll have your action applied to the file just &lt;em&gt;once&lt;/em&gt; rather than having the action applied to each entry.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Which command type you choose will depend on what your &amp;lsquo;action&amp;rsquo; is intending to achieve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s consider an example scenario such as having a quickfix window containing two files:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;example1.txt&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;example2.txt&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The file &lt;code&gt;example1.txt&lt;/code&gt; shows up multiple times, while &lt;code&gt;example2.txt&lt;/code&gt; only shows up once.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The file &lt;code&gt;example1.txt&lt;/code&gt; shows up multiple times because we searched for a phrase such as &lt;code&gt;foo&lt;/code&gt; and that phrase happened to appear multiple times within &lt;code&gt;example1.txt&lt;/code&gt;, while it only appeared once within &lt;code&gt;example2.txt&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you wanted to replace &lt;code&gt;foo&lt;/code&gt; with &lt;code&gt;bar&lt;/code&gt; using a subtitution like &lt;code&gt;s/foo/bar/&lt;/code&gt;, and you used &lt;code&gt;cdo&lt;/code&gt;, then all occurrences of &lt;code&gt;foo&lt;/code&gt; would be replaced (i.e. across both &lt;code&gt;example1.txt&lt;/code&gt; and &lt;code&gt;example2.txt&lt;/code&gt;) because the substitution would be executed across each &lt;em&gt;entry&lt;/em&gt; in the quickfix window.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if you used &lt;code&gt;cfdo&lt;/code&gt; then the substitution would only be applied once to each &lt;em&gt;file&lt;/em&gt;, which would result in &lt;code&gt;example2.txt&lt;/code&gt; having its only instance of &lt;code&gt;foo&lt;/code&gt; replaced with &lt;code&gt;bar&lt;/code&gt; while &lt;code&gt;example1.txt&lt;/code&gt; would have only one instance of &lt;code&gt;foo&lt;/code&gt; replaced with &lt;code&gt;bar&lt;/code&gt; and the other nine instances left unchanged. This is because we didn&amp;rsquo;t provide a &amp;lsquo;range&amp;rsquo;, in this case &lt;code&gt;%&lt;/code&gt;, in our substitution operation (e.g. &lt;code&gt;:%s/foo/bar/&lt;/code&gt; meaning apply the substitution across the entire buffer).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You could still use &lt;code&gt;cfdo&lt;/code&gt; but you would need to specify &lt;code&gt;%&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h3 id=&#34;be-careful-with-tools-that-update-the-quickfix-dynamically&#34;&gt;Be careful with tools that update the quickfix dynamically&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The summary of this subsection is: be aware of any active plugins/tools that might dynamically update your quickfix window while your &lt;code&gt;cdo&lt;/code&gt; command is still running.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To elaborate: I&amp;rsquo;ve found that my quickfix window is updated frequently/dynamically when using certain build tools.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, vim-go using gopls will update the quickfix list every time a file is written to. This is because it wants to display an updated list of files that might potentially contain broken code. That&amp;rsquo;s great when I&amp;rsquo;m generally developing on a go program, but not when I&amp;rsquo;m in the middle of trying to apply a set of changes globally using &lt;code&gt;cdo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this causes problems when trying to apply changes is because &lt;code&gt;cdo&lt;/code&gt; gets confused when it attempts to process the next quickfix entry but discovers the quickfix list of results has changed!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way I could work around this is by using a location list, but most tools I use put results into a quickfix window so that&amp;rsquo;s not going to help me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case I&amp;rsquo;ve found I&amp;rsquo;m better off using &lt;code&gt;cfdo&lt;/code&gt; with &lt;code&gt;%s/foo/bar/e | update&lt;/code&gt; which will write the buffer once, rather than the multiple times when using &lt;code&gt;cdo&lt;/code&gt; with &lt;code&gt;s/foo/bar/e | update&lt;/code&gt;. It&amp;rsquo;s also much more efficient using &lt;code&gt;cfdo&lt;/code&gt; as it won&amp;rsquo;t write the buffer multiple times.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Your mileage may vary, but it&amp;rsquo;s important to think about this if you have certain build tools active that might mess around with the quickfix window half way through you processing the current list of results.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now look at an example where we execute a substitution for every &amp;lsquo;entry&amp;rsquo; listed in the quickfix window:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:cdo s/foo/bar/ | update&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t need to pipe to &lt;a href=&#34;https://vimhelp.org/editing.txt.html#%3Aupdate&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;update&lt;/code&gt;&lt;/a&gt;. I just do that because, most of the time, when I modify a file it&amp;rsquo;s because I want to save the changes 🙂&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, to execute a macro introduces some interesting things to think about. For example, macros only execute &lt;em&gt;once&lt;/em&gt; so if you need them to be executed multiple times, then you need to tell them to execute across a &amp;lsquo;range&amp;rsquo; (e.g. the entire buffer or a section of lines, like &lt;code&gt;%norm! @q&lt;/code&gt;). Having a macro run multiple times is fine when you&amp;rsquo;re dealing with content that is grouped together sequentially, but when wanting to apply a macro on a &amp;lsquo;search pattern&amp;rsquo;, then there&amp;rsquo;s no guarantees that the search results will be in the required order/grouping.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why I always use &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Acdo&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;cdo&lt;/code&gt;&lt;/a&gt; when needing to apply a macro across multiple files (you&amp;rsquo;ll notice I also need to use &lt;a href=&#34;https://vimhelp.org/eval.txt.html#%3Aexecute&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;execute&lt;/code&gt;&lt;/a&gt; so I can evaluate my expression &lt;code&gt;norm @q&lt;/code&gt; as an Ex command):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:cdo execute &amp;quot;norm @q&amp;quot; | update&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;filtering-quickfix-and-location-list-results&#34;&gt;Filtering quickfix and location list results&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s interesting about &amp;lsquo;quickfix&amp;rsquo; and &amp;lsquo;location&amp;rsquo; lists is that you can further filter their results. Now, admittedly if you&amp;rsquo;re using a third-party plugin like &lt;a href=&#34;https://github.com/mileszs/ack.vim&#34; target=&#34;_blank&#34;&gt;Ack&lt;/a&gt;, then yes you do have more control over the search pattern using additional flags provided by a third-party plugin that will help to filter the number of results, but I&amp;rsquo;d argue there are still situations where you need even &lt;em&gt;more&lt;/em&gt; fine grained control over what&amp;rsquo;s displayed in the quickfix/location lists.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;ve taken the purist (i.e. no plugins) approach, then using the built-in Vim search (e.g. &lt;code&gt;vimgrep&lt;/code&gt;/&lt;code&gt;lvimgrep&lt;/code&gt; or even a custom configured &lt;code&gt;grep&lt;/code&gt; to use an external command) will not offer much in the way of configuring the filtering of results (at the end of the day these built-in tools are useful but limited).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what additional tools does Vim provide to us? In this case you can utilise either &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3ACfilter&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Cfilter&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3ALfilter&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Lfilter&lt;/code&gt;&lt;/a&gt; to filter your search results. These two commands are internal Vim plugins that need to be loaded using Vim&amp;rsquo;s &lt;a href=&#34;https://vimhelp.org/repeat.txt.html#%3Apackadd&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;packadd&lt;/code&gt;&lt;/a&gt; command (I actually have this added to my &lt;a href=&#34;https://github.com/Integralist/dotfiles/blob/master/.vimrc#L75-L77&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;.vimrc&lt;/code&gt;&lt;/a&gt; as I always forget to call &lt;code&gt;packadd&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example of how to use &lt;code&gt;Cfilter&lt;/code&gt;. I&amp;rsquo;m going to search for the phrase &amp;ldquo;vim&amp;rdquo; across my blog, which ends up returning quite a few results across multiple files. Turns out I&amp;rsquo;m only interested in files that are Markdown files and so I need to filter the results to only show me those files&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Sure you could use &lt;a href=&#34;https://vimhelp.org/options.txt.html#%27wildignore%27&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;wildignore&lt;/code&gt;&lt;/a&gt; (or maybe even &lt;a href=&#34;https://vimhelp.org/options.txt.html#%27suffixes%27&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;suffixes&lt;/code&gt;&lt;/a&gt;, although it won&amp;rsquo;t solve our problem, only alleviate it slightly) but it&amp;rsquo;s really a &lt;em&gt;hammer&lt;/em&gt; solution, where we want a scalpel.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:vimgrep /vim/ **/*&#xA;:packadd cfilter&#xA;:Cfilter /\.md$/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll see I&amp;rsquo;ve used &lt;code&gt;/&lt;/code&gt; as delimiters around the regex pattern, but you can also use other single-byte characters (refer to &lt;code&gt;:h pattern-delimiter&lt;/code&gt; or &lt;a href=&#34;https://vimhelp.org/change.txt.html#pattern-delimiter&#34; target=&#34;_blank&#34;&gt;the online help&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, so what&amp;rsquo;s interesting here is that &lt;code&gt;Cfilter&lt;/code&gt;/&lt;code&gt;Lfilter&lt;/code&gt; will search (using a regex pattern) &lt;em&gt;both&lt;/em&gt; the filename and the text entry itself. So trying to filter for just &lt;code&gt;\.md&lt;/code&gt; would still include more files than just Markdown files because the content of the file is also searched and I have &lt;code&gt;.txt&lt;/code&gt; files that include both &lt;code&gt;vim&lt;/code&gt; and the filter pattern &lt;code&gt;.md&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why I also use the regex anchor &lt;code&gt;$&lt;/code&gt; because it&amp;rsquo;s less likely for me to accidentally hit a match, and so I&amp;rsquo;m more likely to just get back results that are Markdown files containing the phrase &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As you can see the default behaviour of the filter is to keep only those results that match your pattern. If you want the filter to work in reverse so it &lt;em&gt;removes&lt;/em&gt; anything that matches your pattern, then add &lt;code&gt;!&lt;/code&gt; to the command like so &lt;code&gt;:Cfilter! /your_pattern/&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;As this is a regex pattern you can still use &lt;code&gt;\v&lt;/code&gt; to get &amp;lsquo;magic&amp;rsquo; mode. For example &lt;code&gt;/\vyour_pattern/&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;processing-files-with-t-do&#34;&gt;Processing files with &lt;code&gt;&amp;lt;T&amp;gt;do&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve already seen &lt;code&gt;:cdo&lt;/code&gt; and &lt;code&gt;:cfdo&lt;/code&gt;, but there&amp;rsquo;s so many more &amp;lsquo;do&amp;rsquo; commands that can enrich your Vim experience:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://vimhelp.org/windows.txt.html#%3Abufdo&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:bufdo&lt;/code&gt;&lt;/a&gt;: apply action to all buffers (&lt;a href=&#34;https://vimhelp.org/windows.txt.html#%3Als&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h ls&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://vimhelp.org/tabpage.txt.html#%3Atabdo&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:tabdo&lt;/code&gt;&lt;/a&gt;: apply action to all tabs.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://vimhelp.org/windows.txt.html#%3Awindo&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:windo&lt;/code&gt;&lt;/a&gt;: apply action to all windows (multiple windows might all display the same buffer).&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://vimhelp.org/editing.txt.html#%3Aargdo&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:argdo&lt;/code&gt;&lt;/a&gt;: apply action to all arguments in the &lt;a href=&#34;https://vimhelp.org/editing.txt.html#arglist&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h arglist&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now admittedly I mostly use &lt;code&gt;:cdo&lt;/code&gt;/&lt;code&gt;:cfdo&lt;/code&gt; over any of the above because they are, for me, the most practical tools that give me massive value in my day-to-day work. That said, I do like to use &lt;code&gt;:bufdo&lt;/code&gt; as well (I don&amp;rsquo;t think I ever use &lt;code&gt;:tabdo&lt;/code&gt; or &lt;code&gt;:windo&lt;/code&gt; to be honest, although it&amp;rsquo;s good to know they exist in my toolbox), and the &lt;em&gt;action&lt;/em&gt; I do the most when using &lt;code&gt;:bufdo&lt;/code&gt; is when I want to clear out a bunch of buffers. So I&amp;rsquo;ll run &lt;code&gt;:bufdo bd&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/windows.txt.html#%3Abd&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h bd&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll give you another example of how you might want to use something like &lt;code&gt;:bufdo&lt;/code&gt; which came in handy for me recently. I had a git project which caused a bunch of conflicts in my files when I had rebased another branch. So I opened up all the conflicting files so I could locate the specific git syntax &lt;code&gt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/code&gt; that surrounds where the conflicts were.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point I went through each file and was fixing the issues, but then I realised I wasn&amp;rsquo;t sure if I had fixed all occurrences of &lt;code&gt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/code&gt; in each file I had edited. I guess I could have just run &lt;code&gt;vimgrep&lt;/code&gt; over the whole project, but it&amp;rsquo;s a large project and it would have taken a lot longer than I would have liked because of the fact it was a &lt;em&gt;very&lt;/em&gt; large project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;the solution in this case was to search over the files that I had open using &lt;code&gt;:bufdo&lt;/code&gt; mixed with the &lt;a href=&#34;https://vimhelp.org/eval.txt.html#%3Aexecute&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:execute&lt;/code&gt;&lt;/a&gt; command and the &lt;em&gt;append&lt;/em&gt; specific version of &lt;code&gt;vimgrep&lt;/code&gt; (i.e. &lt;a href=&#34;https://vimhelp.org/quickfix.txt.html#%3Avimgrepa&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;vimgrepa&lt;/code&gt;&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:bufdo execute &amp;quot;vimgrepa /&amp;lt;&amp;lt;&amp;lt; HEAD/ %&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see I was also able to utilise the &lt;a href=&#34;https://vimhelp.org/change.txt.html#%3Aregisters&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;%&lt;/code&gt; register&lt;/a&gt; to access the current file name. So for each iteration of &lt;code&gt;bufdo&lt;/code&gt; through the buffer list, the &lt;code&gt;%&lt;/code&gt; register would be updated to reflect the name of the file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each of these &amp;lsquo;do&amp;rsquo; commands are all fairly self-explanatory, but let&amp;rsquo;s take a moment to look at &lt;code&gt;argdo&lt;/code&gt; as it has some interesting extra considerations. When you open Vim for the first time there is an &amp;lsquo;argument list&amp;rsquo; that gets populated. All files open in the argument list will match what&amp;rsquo;s in your buffer list, unless you start opening/closing buffers. But regardless of changes to the buffer list, the arglist will stay the same, which means just because you have a file name in the argument list doesn&amp;rsquo;t mean you have a buffer open for that file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That last bit is important because it can be a reason for using &lt;code&gt;:argdo&lt;/code&gt; over &lt;code&gt;:bufdo&lt;/code&gt;. Typically they produce the same end result because when you open Vim with three files given as arguments, then the arglist will contain those three file names, but there will also be three buffers opened with those files as content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can&amp;rsquo;t &lt;em&gt;accidentally&lt;/em&gt; add a new argument to the arglist because you have to explicitly call &lt;a href=&#34;https://vimhelp.org/editing.txt.html#%3Aargadd&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:argadd&lt;/code&gt;&lt;/a&gt; (for deleting you need &lt;a href=&#34;https://vimhelp.org/editing.txt.html#%3Aargdelete&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:argdelete&lt;/code&gt;&lt;/a&gt;). Where as with the list of buffers, that gets updated whenever you open a new file (and that is very easily done, especially when searching for content), but importantly the arglist will stay unchanged.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;automating-content-modification-using-ex-commands-from-the-shell&#34;&gt;Automating content modification using Ex commands from the shell&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Vim has a nice feature where it allows you to easily run Ex commands against a file from the shell. The summary of which is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ vim -E -s some_file.txt &amp;lt;&amp;lt;-EOF&#xA;  :%s/foo/bar/&#xA;  :update&#xA;  :quit&#xA;EOF&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But stick around for a few more details&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Vim doesn&amp;rsquo;t handle stdin like other posix commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ echo foo | vim&#xA;&#xA;Vim: Warning: Input is not from a terminal&#xA;Vim: Error reading input, exiting...&#xA;Vim: Finished.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you pass &lt;code&gt;-&lt;/code&gt; to Vim, then it will accept the stdin and copy it to a new buffer&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ echo foo | vim -&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Before we look ahead at how to handle stdin a bit better, let&amp;rsquo;s consider the &lt;code&gt;+&lt;/code&gt; flag which tells Vim what line to start on (the following example tells Vim to jump to line 10):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ vim ~/.vimrc +10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will become relevant when we look at two other flags &lt;code&gt;-e&lt;/code&gt; and &lt;code&gt;-s&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/starting.txt.html#-e&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h -e&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://vimhelp.org/starting.txt.html#-s&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h -s&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://vimhelp.org/starting.txt.html#-s-ex&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h -s-ex&lt;/code&gt;&lt;/a&gt;)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ echo foo | vim - -es +&#39;%p&#39; +&#39;qa!&#39;&#xA;&#xA;Vim: Reading from stdin...&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When using the &lt;code&gt;-e&lt;/code&gt; and &lt;code&gt;-s&lt;/code&gt; flags, we&amp;rsquo;re able to use &lt;code&gt;+&lt;/code&gt; to execute Ex mode commands.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;If you don&amp;rsquo;t use &lt;code&gt;+&#39;qa!&#39;&lt;/code&gt; then Vim will cause the terminal to hang. You also need the &lt;code&gt;!&lt;/code&gt; otherwise &lt;code&gt;qa&lt;/code&gt; would (if dealing with a traditional Vim UI) show a message saying the buffer has been edited and can&amp;rsquo;t be quit.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To avoid the &lt;code&gt;Vim: Reading from stdin...&lt;/code&gt; message we need an additional flag &lt;code&gt;--not-a-term&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ echo foo | vim - -es +&#39;%p&#39; +&#39;qa!&#39; --not-a-term&#xA;&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So now if we want to manipulate the content (let&amp;rsquo;s say uppercase the word &lt;code&gt;foo&lt;/code&gt; to &lt;code&gt;FOO&lt;/code&gt;) we can do:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ echo foo | vim - -es --not-a-term +&#39;norm VgU&#39; +&#39;%p&#39; +&#39;qa!&#39;&#xA;&#xA;FOO&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;norm&lt;/code&gt; says execute the following characters as if the user is typing them, so &lt;code&gt;V&lt;/code&gt; selects the entire line and &lt;code&gt;gU&lt;/code&gt; uppercases the selection. We then print the output to stdout &lt;code&gt;%p&lt;/code&gt; and then quit without trying to save the modifications.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;starting-vim-with-your-last-workspace&#34;&gt;Starting Vim with your last workspace&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now this feature I&amp;rsquo;m going to describe I don&amp;rsquo;t use that often, but there&amp;rsquo;s been a few occasions where it&amp;rsquo;s saved me a lot of hassle. The feature i&amp;rsquo;m going to talk about is &lt;a href=&#34;https://vimhelp.org/starting.txt.html#%3Amksession&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:mksession&lt;/code&gt;&lt;/a&gt;. There are lots of things you can do with &lt;code&gt;:mksession&lt;/code&gt; so read the help documents, but I&amp;rsquo;m only going to cover the basics here because that&amp;rsquo;s mostly all I ever need to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The summary of this Ex command is that it will take a snapshot of your working environment inside Vim and will reproduce it the next time you startup Vim.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way it does this is to stick every buffer, window, window size and layout configuration into a &lt;code&gt;Session.vim&lt;/code&gt; file (don&amp;rsquo;t forget to add this file to your &lt;code&gt;.gitignore&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you need to stop Vim suddenly (for whatever reason) and you don&amp;rsquo;t want to lose your workspace layout because you&amp;rsquo;ve got lots of files open that you&amp;rsquo;d have to write down filename/paths to, and maybe you have specific window splits setup to work on multiple files in a specific order and you don&amp;rsquo;t want to have to remember what the layout was (especially if like me you have multiple Vim tabs open and each one has its own window splits etc) then you just need to run &lt;code&gt;:mksession&lt;/code&gt; before closing Vim.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To start Vim with the session snapshot you would run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;vim -S Session.vim&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it! Your entire workspace is spun up exactly how you left it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you open Vim again you might want to change some of your workspace. If that&amp;rsquo;s the case and you want the &lt;code&gt;Session.vim&lt;/code&gt; file to record that updated layout in its snapshot, then run the &lt;code&gt;:mksession!&lt;/code&gt; command (notice the extra &lt;code&gt;!&lt;/code&gt; at the end to force overwriting the original &lt;code&gt;Session.vim&lt;/code&gt; file).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;vim-s-start-up-process&#34;&gt;Vim&amp;rsquo;s start-up process&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The Vim documentation explains all the various steps that are gone through during &amp;lsquo;start-up&amp;rsquo;, see &lt;a href=&#34;https://vimhelp.org/starting.txt.html#startup&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h startup&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In short, Vim executes &lt;code&gt;:runtime! plugin/**/*.vim&lt;/code&gt; meaning any directories listed in the runtime path (&lt;a href=&#34;https://vimhelp.org/options.txt.html#%27runtimepath%27&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h runtimepath&lt;/code&gt;&lt;/a&gt;) will be searched for a &lt;code&gt;plugin&lt;/code&gt; sub-directory and all files ending in &amp;ldquo;.vim&amp;rdquo; will be sourced (in alphabetical order per directory).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to see what&amp;rsquo;s in your runtime path you can execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:set runtimepath?&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want to debug the start-up process: &lt;a href=&#34;https://vimhelp.org/starting.txt.html#--startuptime&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;vim --startuptime some_log_filename&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To learn more about the various directories Vim uses, then refer to the &lt;code&gt;:help&lt;/code&gt; documentation, for example:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;~/.vim/autoload/...&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/eval.txt.html#autoload&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h autoload&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;~/.vim/plugin/...&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/usr_05.txt.html#plugin&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h plugin&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;~/.vim/ftplugin/...&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/usr_41.txt.html#ftplugin&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h ftplugin&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;~/.vim/after/...&lt;/code&gt; (&lt;a href=&#34;https://vimhelp.org/options.txt.html#after-directory&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h after-directory&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Although I will take a brief detour through that last item&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;the-after-directory&#34;&gt;The &lt;code&gt;after&lt;/code&gt; directory&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;after&lt;/code&gt; directory can be used by both Vim &amp;lsquo;users&amp;rsquo; &lt;em&gt;and&lt;/em&gt; by Vim &amp;lsquo;plugin authors&amp;rsquo; to override specific plugin configuration (that could be either &lt;code&gt;~/.vim/plugin/...&lt;/code&gt; or &lt;code&gt;~/.vim/ftplugin/...&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, the Vim plugin author for &lt;code&gt;vim-polyglot&lt;/code&gt; adds this file: &lt;code&gt;~/.vim/plugin/vim-polyglot/after/ftdetect/rspec.vim&lt;/code&gt; which overrides the filetype configuration for &lt;code&gt;rspec&lt;/code&gt; files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where as a Vim user might want to override the behaviour of a plugin they&amp;rsquo;re using (e.g. the FZF plugin) by adding the file &lt;code&gt;~/.vim/after/plugin/config/fzf.vim&lt;/code&gt;, and due to how Vim loads &amp;lsquo;after&amp;rsquo; scripts, that file would get loaded. Although it&amp;rsquo;s important to add a guard into the code to ensure it only executes if the FZF plugin actually is loaded (otherwise this after script could cause an error)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;&amp;quot; include guard; quit if fzf isn&#39;t loaded&#xA;if ! exists(&#39;:FZF&#39;)&#xA;    finish&#xA;endif&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;debugging-vim-issues&#34;&gt;Debugging Vim issues&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First thing first, run &lt;a href=&#34;https://vimhelp.org/options.txt.html#%3Ase&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:se&lt;/code&gt;&lt;/a&gt; to see all the Vim options that have changed from the Vim defaults. This can be a good &amp;lsquo;at a glance&amp;rsquo; perspective on what might be wrong or why you&amp;rsquo;re seeing some sort of unexpected behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To check a specific setting and who (i.e. which plugin or script) last modified it, use &lt;a href=&#34;https://vimhelp.org/various.txt.html#%3Averbose&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:verbose set &amp;lt;setting&amp;gt;?&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;code&gt;:verbose set shiftwidth?&lt;/code&gt; returns&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;shiftwidth=2&#xA;      Last set from ~/.vimrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also see what mappings have been configured using the &lt;a href=&#34;https://vimhelp.org/map.txt.html#%3Amap&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;map&lt;/code&gt;&lt;/a&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, to see all mappings with the leader key&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:verbose map &amp;lt;leader&amp;gt;&#xA;&#xA;x  \y            :Buffers&amp;lt;CR&amp;gt;&#xA;        Last set from ~/.vimrc&#xA;   \t            :FZF&amp;lt;CR&amp;gt;&#xA;        Last set from ~/.vimrc&#xA;        &#xA;n  \z            :ALEPrevious&amp;lt;CR&amp;gt;&#xA;        Last set from ~/.vimrc&#xA;n  \x            :ALENext&amp;lt;CR&amp;gt;&#xA;        Last set from ~/.vimrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;code&gt;:h map-listing&lt;/code&gt; for the various modes (&lt;code&gt;n&lt;/code&gt; = normal, &lt;code&gt;x&lt;/code&gt; = visual, etc).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The same principle works with other mappings like &lt;code&gt;&amp;lt;Ctrl-k&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Ctrl-j&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:verbose map &amp;lt;c-k&amp;gt;&#xA;&#xA;n  &amp;lt;C-K&amp;gt;         &amp;lt;Plug&amp;gt;MoveLineUp&#xA;        Last set from ~/.vim/plugged/vim-move/plugin/move.vim&#xA;v  &amp;lt;C-K&amp;gt;         &amp;lt;Plug&amp;gt;MoveBlockUp&#xA;        Last set from ~/.vim/plugged/vim-move/plugin/move.vim&#xA;&#xA;:verbose map &amp;lt;c-j&amp;gt;&#xA;&#xA;n  &amp;lt;NL&amp;gt;          &amp;lt;Plug&amp;gt;MoveLineDown&#xA;        Last set from ~/.vim/plugged/vim-move/plugin/move.vim&#xA;v  &amp;lt;NL&amp;gt;          &amp;lt;Plug&amp;gt;MoveBlockDown&#xA;        Last set from ~/.vim/plugged/vim-move/plugin/move.vim&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to know what the default commands that Vim defines, then take a look at &lt;a href=&#34;https://vimhelp.org/index.txt.html#index&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;:h index&lt;/code&gt;&lt;/a&gt; and drill down into the various commands per &amp;lsquo;mode&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Vim also has a debugger you can use: &lt;code&gt;vim -D ~/.vimrc&lt;/code&gt; (see reference below for details).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Lastly, there is the &lt;code&gt;-V&amp;lt;N&amp;gt;&lt;/code&gt; flag that sets the verbosity of Vim output when starting up&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;&amp;quot; &amp;gt;= 1  When the viminfo file is read or written.&#xA;&amp;quot; &amp;gt;= 2  When a file is &amp;quot;:source&amp;quot;&#39;ed.&#xA;&amp;quot; &amp;gt;= 5  Every searched tags file and include file.&#xA;&amp;quot; &amp;gt;= 8  Files for which a group of autocommands is executed.&#xA;&amp;quot; &amp;gt;= 9  Every executed autocommand.&#xA;&amp;quot; &amp;gt;= 12 Every executed function.&#xA;&amp;quot; &amp;gt;= 13 When an exception is thrown, caught, finished, or discarded.&#xA;&amp;quot; &amp;gt;= 14 Anything pending in a &amp;quot;:finally&amp;quot; clause.&#xA;&amp;quot; &amp;gt;= 15 Every executed Ex command (truncated at 200 characters).&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;code&gt;:h vbs&lt;/code&gt; for details.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Usage example: &lt;code&gt;vim -V9 ~/.vimrc&lt;/code&gt;, but you can also write the output to a log file instead (pro tip: use the log file approach) such as &lt;code&gt;vim -V9foo ~/.vimrc&lt;/code&gt; which will write the output to the log file &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, time for the short sections&amp;hellip; 🙂&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;autocomplete-with-no-plugins&#34;&gt;Autocomplete with no plugins&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So you want some form of auto-complete feature without the need for a third-party plugin, no problem&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;filetype plugin on&#xA;set omnifunc=syntaxcomplete#Complete&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you can execute &lt;code&gt;&amp;lt;C-x&amp;gt;&amp;lt;C-o&amp;gt;&lt;/code&gt; to get a very basic form of native code autocompletion.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Vim also provides the native command &lt;code&gt;&amp;lt;C-n&amp;gt;&lt;/code&gt; for autocompletion based on words existing in all opened buffers.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understanding-line-feed-and-carriage-returns&#34;&gt;Understanding line feed and carriage returns&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t necessarily a Vim specific thing but it used to catch me out all the time. &lt;em&gt;Looking&lt;/em&gt; for line breaks and &lt;em&gt;inserting&lt;/em&gt; line breaks are two different things.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The term &lt;strong&gt;CRLF&lt;/strong&gt; refers to Carriage Return (ASCII 13, &lt;code&gt;\r&lt;/code&gt;) Line Feed (ASCII 10, &lt;code&gt;\n&lt;/code&gt;). They&amp;rsquo;re used to note the termination of a line, however, dealt with differently in today&amp;rsquo;s popular Operating Systems.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Windows: CRLF (&lt;code&gt;\r\n&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Linux/Unix: LF (&lt;code&gt;\n&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Imagine in Vim you have a buffer like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;a&#xA;b&#xA;c&#xA;d&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you wanted to add an extra line space between each line, so it looked like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;a&#xA;&#xA;b&#xA;&#xA;c&#xA;&#xA;d&#xA;&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You would need to use a substitution like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:%s/\n/\r\r/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice we&amp;rsquo;re looking for a &amp;lsquo;line feed&amp;rsquo; &lt;code&gt;\n&lt;/code&gt; (because that&amp;rsquo;s how macOS denotes a new line), while to get Vim to insert a line break we need it to &lt;em&gt;insert&lt;/em&gt; two separate &amp;lsquo;carriage returns&amp;rsquo; &lt;code&gt;\r&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;auto-highlighting-keywords-and-creating-your-own-custom-highlighting&#34;&gt;Auto highlighting keywords (and creating your own custom highlighting)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Vim can highlight certain words inside of code comments, such as&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;BUG&lt;/code&gt; (Golang)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;FIXME&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;NOTE&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;NOTES&lt;/code&gt; (Python)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;TODO&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;XXX&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The &lt;code&gt;NOTE&lt;/code&gt; works in both Go and Python files and yet it&amp;rsquo;s not defined in the Go syntax file, which means it&amp;rsquo;s likely inherited from a default syntax file.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;See the syntax files for&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/vim/vim/blob/a87b72cc316e065d66dcbcf7ec1cde330adef3a3/runtime/syntax/python.vim#L134&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/vim/vim/blob/a87b72cc316e065d66dcbcf7ec1cde330adef3a3/runtime/syntax/go.vim#L95&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You can add your own, see &lt;a href=&#34;https://vi.stackexchange.com/a/15531&#34; target=&#34;_blank&#34;&gt;this StackOverflow post&lt;/a&gt; for the full details, but in summary it looks something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vim&#34;&gt;augroup myTodo&#xA;  autocmd!&#xA;  autocmd Syntax * syntax match myTodo /\v\_.&amp;lt;(TODO|FIXME).*/hs=s+1 containedin=.*Comment&#xA;augroup END&#xA;&#xA;highlight link myTodo Todo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;sorting-and-filtering-duplicates&#34;&gt;Sorting and filtering duplicates&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is such a small &amp;lsquo;tip&amp;rsquo;, and is probably obvious to most Vim users, but just in case it isn&amp;rsquo;t&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have some content that consists of a list that might also contain some duplicates, like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo&#xA;bar&#xA;baz&#xA;foo&#xA;bar&#xA;baz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To sort the contents you just need:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:sort&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Resulting in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bar&#xA;bar&#xA;baz&#xA;baz&#xA;foo&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;While if you wanted to remove the duplicates too you would pass &lt;code&gt;u&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-viml&#34;&gt;:sort u&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Resulting in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bar&#xA;baz&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;miscellaneous-tips-and-tricks&#34;&gt;Miscellaneous tips and tricks&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you need your cursor to always be in the middle of the screen (this is modifying the &amp;lsquo;scroff offset&amp;rsquo; option):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;:set so=999&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Move the cursor to the top, middle, bottom of the visible screen:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;H&lt;/code&gt;: high (i.e. top of the screen)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;M&lt;/code&gt;: middle&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;L&lt;/code&gt;: low (i.e. bottom of the screen)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So there you have it, my collection of useful Vim features that I use regularly. Let me know what you think. Anything surprising? What do you use that maybe I&amp;rsquo;ve missed?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thanks for reading! ❤️&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/vim-advanced/</guid>
      <link>https://www.integralist.co.uk/posts/vim-advanced/</link>
      <pubDate>Tue, 15 Jun 2021 00:00:00 +0000</pubDate>
      <title>Advanced Vim topics, tips and tricks</title>
    </item>
    <item>
      <description>&lt;p&gt;I&amp;rsquo;ve been learning &lt;a href=&#34;https://www.rust-lang.org/&#34; target=&#34;_blank&#34;&gt;Rust&lt;/a&gt; recently. This will probably be my &lt;em&gt;third&lt;/em&gt; (lazy) attempt to learn the language. The reason I&amp;rsquo;ve failed previously is simply because I had no reason to learn it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other than the memory safety aspects, which I like a lot, I don&amp;rsquo;t actually like the &lt;em&gt;design&lt;/em&gt; of the language at all (but that&amp;rsquo;s a conversation for another day).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This time around I want to learn the language as it&amp;rsquo;s pertinent to my job. A few months ago I started working for &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt; as a Staff Software Engineer in their Developer Relations team, and their powerful &lt;a href=&#34;https://www.fastly.com/products/edge-compute/features&#34; target=&#34;_blank&#34;&gt;Compute@Edge&lt;/a&gt; platform has strong support for Rust.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I want to start building things on the Compute@Edge platform, so here I am giving Rust another go (at least until &lt;a href=&#34;https://tinygo.org/&#34; target=&#34;_blank&#34;&gt;TinyGo&lt;/a&gt; support matures).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I know from prior experience the real learning curve involved with this language is going to be its memory management model, which is broken down into three sections:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html&#34; target=&#34;_blank&#34;&gt;Ownership&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html&#34; target=&#34;_blank&#34;&gt;Borrowing&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://doc.rust-lang.org/stable/book/ch10-03-lifetime-syntax.html&#34; target=&#34;_blank&#34;&gt;Lifetimes&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Understanding the first section (ownership) requires an understanding of &amp;lsquo;stack&amp;rsquo; vs &amp;lsquo;heap&amp;rsquo; memory, which you may be unfamiliar with depending on your programming experience and if you&amp;rsquo;ve used only high-level programming languages. So here&amp;rsquo;s a quick rundown&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;stack-memory&#34;&gt;Stack Memory&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The stack is memory that is available to your program at runtime. Data that is assigned to variables or passed as arguments to function calls are allocated onto the stack in a &amp;lsquo;Last In, First Out&amp;rsquo; (LIFO) model, much like a stack of plates.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only type of data that can be stored on the stack is data that has a known and fixed size. All other &amp;lsquo;unknown&amp;rsquo; data must go onto the heap.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The stack is very fast to access data because the data is close together, unlike heap memory, and also because the data that is stored is literal (i.e. primitive types like string literals, booleans, integers etc) it means the data itself can be hard coded into the compiled Rust binary.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Rust primitive/scalar types (int, bool, float, char, string literal etc) are stored in stack memory.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;heap-memory&#34;&gt;Heap Memory&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The heap is memory that is also available to your program at runtime but is much slower to access than stack memory. This is because it requires a &amp;lsquo;pointer&amp;rsquo; to locate the stored data, of which the storage area is large and very unorganized.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The heap is for memory that grows or has unknown size (such as when accepting user input, you don&amp;rsquo;t know what data will be provided), and it will be allocated onto the heap by a &amp;lsquo;memory allocator&amp;rsquo; that needs to first find a space in the heap large enough to hold the data, and then return a pointer to that space in the heap.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;**Rust complex types (String, Box etc.) are stored into heap memory.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;ownership&#34;&gt;Ownership&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The rules for ownership are quite simple:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Data is assigned to a variable.&lt;/li&gt;&#xA;&lt;li&gt;The variable becomes the &amp;lsquo;owner&amp;rsquo; of the data.&lt;/li&gt;&#xA;&lt;li&gt;There can only be one owner at a time.&lt;/li&gt;&#xA;&lt;li&gt;When the owner goes out of scope, the data will be dropped.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Primitive types are popped from stack memory automatically when they go out of scope (e.g. when a function block ends), while complex types must implement a &lt;code&gt;drop&lt;/code&gt; function which Rust will call when out of scope (to explicitly deallocate the heap memory).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here are some of the gotchas that trip people up:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Primitive types are &lt;em&gt;copied&lt;/em&gt; (because it&amp;rsquo;s cheap to copy stack memory).&lt;/li&gt;&#xA;&lt;li&gt;Primitive types have a &lt;code&gt;Copy&lt;/code&gt; trait that enable this behaviour.&lt;/li&gt;&#xA;&lt;li&gt;Complex types &lt;em&gt;move&lt;/em&gt; ownership.&lt;/li&gt;&#xA;&lt;li&gt;Complex types do not have a &lt;code&gt;Copy&lt;/code&gt; trait.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As an example, consider the following code, which compiles correctly because we&amp;rsquo;re dealing with primitives and so the &lt;code&gt;println!()&lt;/code&gt; macro used is safely able to reference both the variable &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let a = 123;&#xA;    let b = a;&#xA;    &#xA;    println!(&amp;quot;a: {}, b: {}&amp;quot;, a, b); // a: 123, b: 123&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now consider a similar example which &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; work because we&amp;rsquo;re dealing with a complex type (&lt;code&gt;String&lt;/code&gt;). The value assigned to &lt;code&gt;a&lt;/code&gt; is &lt;em&gt;moved&lt;/em&gt; to &lt;code&gt;b&lt;/code&gt;. The &lt;code&gt;b&lt;/code&gt; variable has now become the new &lt;em&gt;owner&lt;/em&gt; of the data, and this means &lt;code&gt;a&lt;/code&gt; is not allowed to be used again (e.g. we can&amp;rsquo;t reference it in &lt;code&gt;println!()&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let a = String::from(&amp;quot;foo&amp;quot;);&#xA;    let b = a;&#xA;    &#xA;    println!(&amp;quot;a: {}, b: {}&amp;quot;, a, b); // COMPILER ERROR&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will generate the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;error[E0382]: borrow of moved value: `a`&#xA; --&amp;gt; src/main.rs:5:30&#xA;  |&#xA;2 |     let a = String::from(&amp;quot;foo&amp;quot;);&#xA;  |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait&#xA;3 |     let b = a;&#xA;  |             - value moved here&#xA;4 |     &#xA;5 |     println!(&amp;quot;a: {}, b: {}&amp;quot;, a, b);&#xA;  |                              ^ value borrowed here after move&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The only solution here is to manually &lt;em&gt;copy&lt;/em&gt; the value using the &lt;a href=&#34;https://doc.rust-lang.org/alloc/string/struct.String.html#impl-Clone&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;.clone()&lt;/code&gt;&lt;/a&gt; method of the &lt;code&gt;String&lt;/code&gt; type, which means &lt;code&gt;b&lt;/code&gt; no longer becomes the new owner of the data (the data itself is duplicated and so it&amp;rsquo;s &lt;em&gt;new&lt;/em&gt; data that &lt;code&gt;b&lt;/code&gt; is the owner of):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let a = String::from(&amp;quot;foo&amp;quot;);&#xA;    let b = a.clone();&#xA;    &#xA;    println!(&amp;quot;a: {}, b: {}&amp;quot;, a, b); // a: foo, b: foo&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Using &lt;code&gt;clone()&lt;/code&gt; will duplicate the heap memory, which isn&amp;rsquo;t cheap. This forces the programmer to opt into this more expensive behaviour, and is a performance/design decision most users of high-level programming languages don&amp;rsquo;t often have to think about.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to realise that passing a variable to a function will either move or copy (just as assignment does), and that even a function&amp;rsquo;s return value can transfer ownership in the same way. So for example, returning a complex type will move ownership to the caller (and the variable the returned value is assigned to becomes the new owner).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In that scenario the complex type&amp;rsquo;s &lt;code&gt;drop&lt;/code&gt; function is &lt;em&gt;not&lt;/em&gt; called, as would normally be the case if a variable went out of scope at the end of a function (even if the original variable/owner was created within the function) as the compiler is able to determine that the value shouldn&amp;rsquo;t be dropped and instead is being &lt;em&gt;moved&lt;/em&gt; to a new owner somewhere else in your program.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;borrowing&#34;&gt;Borrowing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The concept of borrowing is designed to make dealing with ownership changes easier. It does this by avoiding the &lt;em&gt;moving&lt;/em&gt; of owners. The way it does this is by letting your program provide a &amp;lsquo;reference&amp;rsquo; to the data. This means the receiver of the reference (e.g. a function, struct field or a variable etc) can use the value temporarily without taking ownership of it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To pass a reference instead of passing over ownership, all you have to do is prefix your variable with an ampersand:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    borrow(&amp;amp;s) // pass a &#39;reference&#39; to s&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;String) { // accept a &#39;reference type&#39;&#xA;    println!(&amp;quot;s: {}&amp;quot;, s);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example, the &lt;code&gt;s&lt;/code&gt; argument variable of the &lt;code&gt;borrow&lt;/code&gt; function will be created on the stack, and will &lt;em&gt;point&lt;/em&gt; to data in heap memory. When the &lt;code&gt;borrow&lt;/code&gt; function finishes and the &lt;code&gt;s&lt;/code&gt; variable is popped off the stack it won&amp;rsquo;t delete any data because it never owned the data that &lt;code&gt;s&lt;/code&gt; was pointing to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing you&amp;rsquo;ll likely want to do in your programs is to have functions that borrow data to be able to &lt;em&gt;mutate&lt;/em&gt; it. That&amp;rsquo;s simple enough by using the &lt;a href=&#34;https://doc.rust-lang.org/std/keyword.mut.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;mut&lt;/code&gt;&lt;/a&gt; keyword.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice in the below example code we not only define the &lt;code&gt;main&lt;/code&gt; function&amp;rsquo;s &lt;code&gt;s&lt;/code&gt; variable to be mutable but we also have to change the reference in the call to &lt;code&gt;borrow()&lt;/code&gt; as well as the &lt;code&gt;borrow&lt;/code&gt; function&amp;rsquo;s signature to accept a mutable reference.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also notice that after borrowing the value, we call &lt;code&gt;take_ownership()&lt;/code&gt; and we don&amp;rsquo;t pass a &amp;lsquo;reference&amp;rsquo;, meaning the function is the new owner of the data that was belonging to &lt;code&gt;s&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    println!(&amp;quot;s: {}&amp;quot;, s); // s: foo&#xA;    &#xA;    borrow(&amp;amp;mut s);&#xA;    &#xA;    println!(&amp;quot;s: {}&amp;quot;, s); // s: foobar&#xA;    &#xA;    take_ownership(s);&#xA;    &#xA;    println!(&amp;quot;s: {}&amp;quot;, s); // COMPILER ERROR (ownership of s was moved)&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&#xA;fn take_ownership(s: String) {&#xA;    println!(&amp;quot;s: {}&amp;quot;, s); // s: foobar&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also important at this point to understand that defining a variable as being &amp;lsquo;mutable&amp;rsquo; and passing a &amp;lsquo;mutable reference&amp;rsquo; are two different things. You can see in the below example code that we have said &lt;code&gt;s&lt;/code&gt; is mutable and then we pass it as an immutable reference to &lt;code&gt;borrow_no_mut()&lt;/code&gt; and then as a mutable reference to &lt;code&gt;borrow_with_mut()&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    borrow_no_mut(&amp;amp;s);&#xA;    borrow_with_mut(&amp;amp;mut s);&#xA;    &#xA;    println!(&amp;quot;s: {}&amp;quot;, s) // foobar&#xA;}&#xA;&#xA;fn borrow_no_mut(s: &amp;amp;String) {&#xA;    println!(&amp;quot;s: {}&amp;quot;, s) // foo&#xA;}&#xA;&#xA;fn borrow_with_mut(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;gotchas&#34;&gt;Gotchas&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can&amp;rsquo;t take a reference and then modify the original variable&amp;rsquo;s value.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s an example that doesn&amp;rsquo;t compile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut x;&#xA;    x = 42;&#xA;    let y = &amp;amp;x;&#xA;    x = 43;&#xA;    println!(&amp;quot;{:?}&amp;quot;, y);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we define &lt;code&gt;x&lt;/code&gt; and assign the value &lt;code&gt;42&lt;/code&gt;. Next we define &lt;code&gt;y&lt;/code&gt; and take a reference to &lt;code&gt;x&lt;/code&gt; (i.e. we &amp;lsquo;borrow&amp;rsquo; it). Lastly we try to reassign a new value to &lt;code&gt;x&lt;/code&gt; while still holding a reference to it, which isn&amp;rsquo;t allowed because it would potentially invalidate the reference.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This would result in the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ cargo run&#xA;   Compiling chapter1 v0.1.0 (/Users/integralist/Code/rust/rust-for-rustaceans/chapter1)&#xA;warning: value assigned to `x` is never read&#xA; --&amp;gt; src/main.rs:5:5&#xA;  |&#xA;5 |     x = 43;&#xA;  |     ^&#xA;  |&#xA;  = note: `#[warn(unused_assignments)]` on by default&#xA;  = help: maybe it is overwritten before being read?&#xA;&#xA;error[E0506]: cannot assign to `x` because it is borrowed&#xA; --&amp;gt; src/main.rs:5:5&#xA;  |&#xA;4 |     let y = &amp;amp;x;&#xA;  |             -- borrow of `x` occurs here&#xA;5 |     x = 43;&#xA;  |     ^^^^^^ assignment to borrowed `x` occurs here&#xA;6 |     println!(&amp;quot;{:?}&amp;quot;, y);&#xA;  |                      - borrow later used here&#xA;&#xA;For more information about this error, try `rustc --explain E0506`.&#xA;warning: `chapter1` (bin &amp;quot;chapter1&amp;quot;) generated 1 warning&#xA;error: could not compile `chapter1` due to previous error; 1 warning emitted&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To solve this problem you need &lt;code&gt;y&lt;/code&gt; to fall out of scope (or alternatively create a function so that when the function is called with a reference the reference drops out of scope at the end). This can be done using block scope syntax like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut x;&#xA;    x = 42;&#xA;    {&#xA;        let y = &amp;amp;x;&#xA;        println!(&amp;quot;{:?}&amp;quot;, y); // 42&#xA;    }&#xA;    x = 43;&#xA;    println!(&amp;quot;{:?}&amp;quot;, x); // 43&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another &lt;em&gt;gotcha&lt;/em&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can have only &lt;strong&gt;one&lt;/strong&gt; mutable reference (i.e. this prevents data races).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;&lt;em&gt;unless&lt;/em&gt;! the scope allows for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here is an example where it &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; allowed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    let a = &amp;amp;mut s;&#xA;    &#xA;    borrow(a);&#xA;    &#xA;    let b = &amp;amp;mut s;&#xA;    &#xA;    borrow(b);&#xA;    &#xA;    println!(&amp;quot;a: {}&amp;quot;, a); // COMPILER ERROR&#xA;    println!(&amp;quot;b: {}&amp;quot;, b);&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make this example work we need the scope rules to allow for it, which means moving the first mutable reference assignment into its own block where the end of the newly defined block&amp;rsquo;s scope will cause &lt;code&gt;a&lt;/code&gt; to be dropped:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    {&#xA;        let a = &amp;amp;mut s;&#xA;        borrow(a);&#xA;        println!(&amp;quot;a: {}&amp;quot;, a); // foobar&#xA;    } // &amp;lt;-- a is dropped&#xA;    &#xA;    let b = &amp;amp;mut s;&#xA;    borrow(b);&#xA;    println!(&amp;quot;b: {}&amp;quot;, b); // foobarbar&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another &lt;em&gt;gotcha&lt;/em&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You cannot have a mutable reference &lt;em&gt;and&lt;/em&gt; an immutable reference.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s an example where the compiler complains:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    let a = &amp;amp;s;     // immutable reference&#xA;    let b = &amp;amp;mut s; // mutable reference&#xA;    &#xA;    borrow(b);&#xA;    &#xA;    println!(&amp;quot;a: {}&amp;quot;, a); // COMPILER ERROR&#xA;    println!(&amp;quot;b: {}&amp;quot;, b);&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Multiple immutable references are safe because you&amp;rsquo;re only able to &lt;em&gt;read&lt;/em&gt; the data and not mutate it, but you cannot have an immutable reference while also holding a mutable reference because this otherwise could change the value of the immutable reference (and that would be unexpected for the part of the program using the immutable reference).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only way this would be allowed is if the immutable reference goes out of scope before the mutable reference(s) were assigned:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let mut s = String::from(&amp;quot;foo&amp;quot;);&#xA;    &#xA;    {&#xA;        let a = &amp;amp;s;&#xA;        println!(&amp;quot;a: {}&amp;quot;, a); // foo&#xA;    } // &amp;lt;-- immutable reference `a` is dropped&#xA;    &#xA;    let b = &amp;amp;mut s;&#xA;    borrow(b);&#xA;    println!(&amp;quot;b: {}&amp;quot;, b); // foobar&#xA;}&#xA;&#xA;fn borrow(s: &amp;amp;mut String) {&#xA;    s.push_str(&amp;quot;bar&amp;quot;);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One last gotcha:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can&amp;rsquo;t return a function defined variable as a reference.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s what that might look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let r = return_ref();&#xA;    println!(&amp;quot;r: {}&amp;quot;, r); // foo&#xA;}&#xA;&#xA;fn return_ref&amp;lt;&#39;a&amp;gt;() -&amp;gt; &amp;amp;&#39;a String {&#xA;    let s = String::from(&amp;quot;foo&amp;quot;);&#xA;    return &amp;amp;s; // COMPILER ERROR&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;&amp;lt;&#39;a&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;amp;&#39;a&lt;/code&gt; syntax will be explained in the next section called &amp;ldquo;Lifetimes&amp;rdquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The above code will cause the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;error[E0515]: cannot return reference to local variable `s`&#xA; --&amp;gt; src/main.rs:8:12&#xA;  |&#xA;8 |     return &amp;amp;s; // COMPILER ERROR&#xA;  |            ^^ returns a reference to data owned by the current function&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you look at the compiler explanation for the error (&lt;code&gt;rustc --explain E0515&lt;/code&gt;) it describes the reason, and the solution:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Local variables, function parameters and temporaries are all dropped before the end of the function body. So a reference to them cannot be returned. Consider returning an owned value instead.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So the solution to this problem is to &amp;lsquo;move&amp;rsquo; ownership of the data to whoever is calling the function, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let r = return_ref();&#xA;    println!(&amp;quot;r: {}&amp;quot;, r); // foo&#xA;}&#xA;&#xA;fn return_ref() -&amp;gt; String {&#xA;    let s = String::from(&amp;quot;foo&amp;quot;);&#xA;    return s;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example the &lt;code&gt;r&lt;/code&gt; variable is now the new owner of the data.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;lifetimes&#34;&gt;Lifetimes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Lifetimes are tightly coupled to &amp;lsquo;references&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A &amp;lsquo;lifetime&amp;rsquo; is how long a reference lives for, and the compiler wants to be sure that any reference that is currently active doesn&amp;rsquo;t refer to data that no longer exists (i.e. a &amp;lsquo;dangling pointer&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The compiler needs a way to track a reference so it can be sure the reference lives long enough for no errors to occur. To achieve this goal, the Rust compiler uses a &amp;ldquo;borrow checker&amp;rdquo; to validate a reference&amp;rsquo;s lifetime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how do we identify the lifetime of a reference? Well, it begins when the reference is created and it ends when the reference is &lt;em&gt;last used&lt;/em&gt; (you might have expected it to be when the reference was dropped/out of scope, which would be incorrect).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What does a lifetime look like? It&amp;rsquo;s just an annotation that has a specific naming convention: &lt;code&gt;&#39;&amp;lt;T&amp;gt;&lt;/code&gt; where &lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt; is a letter like &lt;code&gt;&#39;a&lt;/code&gt; or &lt;code&gt;&#39;b&lt;/code&gt;. The letters don&amp;rsquo;t mean anything special, they&amp;rsquo;re just a way for the compiler to track a reference.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Rust online book has a good example of this, where they define a function that accepts two arguments &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; (both of type &lt;code&gt;&amp;amp;str&lt;/code&gt;, i.e. a string literal) and depending on the length of the given strings you&amp;rsquo;ll get back either the &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; string.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Without the lifetime feature this would be a problem for the compiler because it wouldn&amp;rsquo;t be able to statically determine which variable (&lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;) is going to be returned. That can only be determined at &lt;em&gt;runtime&lt;/em&gt; not compile time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The below code example highlights how defining a single lifetime called &lt;code&gt;&#39;a&lt;/code&gt; and assigning it to both arguments (and to the return value) allows the compiler to track these references and ensure they both live long enough to prevent any errors at runtime.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn longest&amp;lt;&#39;a&amp;gt;(x: &amp;amp;&#39;a str, y: &amp;amp;&#39;a str) -&amp;gt; &amp;amp;&#39;a str {&#xA;    if x.len() &amp;gt; y.len() {&#xA;        x&#xA;    } else {&#xA;        y&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code states all the references in the signature must have the same lifetime, and it tells the borrow checker it should reject any values that don&amp;rsquo;t adhere to these constraints.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means that if either of the arguments &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; don&amp;rsquo;t live long enough to be used safely, the compiler will let you know about it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example that demonstrates the potential error when the code is poorly designed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    let string1 = String::from(&amp;quot;a very long string&amp;quot;);&#xA;    let result;&#xA;    {&#xA;        let string2 = String::from(&amp;quot;short string&amp;quot;);&#xA;        result = longest(string1.as_str(), string2.as_str());&#xA;    }&#xA;    println!(&amp;quot;The longest string is {}&amp;quot;, result);&#xA;}&#xA;&#xA;fn longest&amp;lt;&#39;a&amp;gt;(x: &amp;amp;&#39;a str, y: &amp;amp;&#39;a str) -&amp;gt; &amp;amp;&#39;a str {&#xA;    if x.len() &amp;gt; y.len() {&#xA;        x&#xA;    } else {&#xA;        y&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code will cause the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;error[E0597]: `string2` does not live long enough&#xA; --&amp;gt; src/main.rs:6:44&#xA;  |&#xA;6 |         result = longest(string1.as_str(), string2.as_str());&#xA;  |                                            ^^^^^^^ borrowed value does not live long enough&#xA;7 |     }&#xA;  |     - `string2` dropped here while still borrowed&#xA;8 |     println!(&amp;quot;The longest string is {}&amp;quot;, result);&#xA;  |                                          ------ borrow later used here&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Although I&amp;rsquo;m very new to these concepts that Rust defines, I get the feeling that although understanding them at a high-level (as I&amp;rsquo;ve described them in this post) is reasonably easy. Being able to fully appreciate them and more importantly getting &lt;em&gt;comfortable&lt;/em&gt; with them is just something that&amp;rsquo;s going to take time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let me know if this helped you. Reach out to me on twitter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/rust-ownership/</guid>
      <link>https://www.integralist.co.uk/posts/rust-ownership/</link>
      <pubDate>Sun, 28 Mar 2021 00:00:00 +0000</pubDate>
      <title>Rust Ownership, Borrowing, and Lifetimes</title>
    </item>
    <item>
      <description>&lt;p&gt;I&amp;rsquo;m going to walk you through how to understand reflection in Go using the &lt;a href=&#34;https://golang.org/pkg/reflect/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;reflect&lt;/code&gt;&lt;/a&gt; package. We&amp;rsquo;ll do this by looking at an open-source package I created called &lt;a href=&#34;https://github.com/integralist/go-flags&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;go-flags&lt;/code&gt;&lt;/a&gt; that utilizes reflection &lt;em&gt;heavily&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The use of reflection is often frowned upon because it side steps the &amp;lsquo;compile time&amp;rsquo; type safety we get in Go. So I&amp;rsquo;ll also explain how we can still ensure a level of type safety even at runtime.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-reflection&#34;&gt;What is reflection?&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reflection in computing is the ability of a program to examine its own structure, particularly through types; it&amp;rsquo;s a form of metaprogramming. It&amp;rsquo;s also a great source of confusion.&lt;br&gt;&#xA;&amp;ndash; &lt;a href=&#34;https://blog.golang.org/laws-of-reflection&#34; target=&#34;_blank&#34;&gt;The Laws of Reflection&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The above quote comes from the opening of the Go Blog post &lt;a href=&#34;https://blog.golang.org/laws-of-reflection&#34; target=&#34;_blank&#34;&gt;The Laws of Reflection&lt;/a&gt; and I &lt;em&gt;strongly&lt;/em&gt; recommend you read it, as it breaks down how types and interfaces work in Go (which is a prerequisite to understanding reflection) before leading into how reflection itself works.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There will be a summarized version of that information here, but ultimately what differentiates their post from mine is that I&amp;rsquo;ll be discussing examples that are more practical and based on a &lt;em&gt;real&lt;/em&gt; project (e.g. &lt;a href=&#34;https://github.com/integralist/go-flags&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;go-flags&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understanding-interfaces-in-go&#34;&gt;Understanding Interfaces in Go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In Go an &amp;lsquo;interface type&amp;rsquo; is a collection of methods which can be defined like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Foo interface {&#xA;    Bar(s string)&#xA;    Baz(i int)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you define a variable to be of type &lt;code&gt;Foo&lt;/code&gt;, then you&amp;rsquo;re saying the value that is assigned to the variable can be &lt;em&gt;any&lt;/em&gt; type that implements the methods as defined by the &lt;code&gt;Foo&lt;/code&gt; interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Conceptually the variable containing the assigned value can be thought of as a tuple that contains the underlying concrete value and the concrete type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is best demonstrated in an example. Below we create an interface type &lt;code&gt;Foo&lt;/code&gt;, and then we define a struct type that will implement that interface. We&amp;rsquo;ll assign an instance of the struct to a variable defined as being an interface type of &lt;code&gt;Foo&lt;/code&gt; and we&amp;rsquo;ll inspect the code at runtime using the &lt;code&gt;reflect&lt;/code&gt; package to see what it can tell us about the variable and what it contains:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;reflect&amp;quot;&#xA;)&#xA;&#xA;type Foo interface {&#xA;    Bar(s string)&#xA;    Baz(i int)&#xA;}&#xA;&#xA;type T struct{&#xA;    s string&#xA;    i int&#xA;}&#xA;&#xA;func (t T) Bar(s string) {&#xA;    //&#xA;}&#xA;&#xA;func (t T) Baz(i int) {&#xA;    //&#xA;}&#xA;&#xA;func main() {&#xA;    var f Foo&#xA;    f = T{&amp;quot;testing&amp;quot;, 123}&#xA;&#xA;    fmt.Printf(&amp;quot;(%+v, %+v)\n&amp;quot;, reflect.ValueOf(f), reflect.TypeOf(f))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the above program is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;({s:testing i:123}, main.T)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so we can see that the &amp;lsquo;value&amp;rsquo; assigned to the &lt;code&gt;f&lt;/code&gt; variable (of interface type &lt;code&gt;Foo&lt;/code&gt;) is a struct with the relevant fields assigned with the appropriate value types. We can also see that the &amp;lsquo;type&amp;rsquo; of the value is &lt;code&gt;main.T&lt;/code&gt;, which is correct and expected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So this clearly demonstrates that although we&amp;rsquo;ve stated the variable &lt;code&gt;f&lt;/code&gt; should hold an interface type of &lt;code&gt;Foo&lt;/code&gt;, it&amp;rsquo;s actually holding a different type entirely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This probably sounds like common sense (and as such not that interesting) but if you really think about it, that&amp;rsquo;s incredible. We&amp;rsquo;ve not explicitly declared the &lt;code&gt;T&lt;/code&gt; struct as implementing the &lt;code&gt;Foo&lt;/code&gt; interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead the fact it does implement the interface, and doing so is being &lt;em&gt;dynamically&lt;/em&gt; understood by the compiler is a super powerful feature.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-do-we-need-reflection&#34;&gt;Why do we need Reflection?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You need reflection whenever dealing with information that wasn&amp;rsquo;t known at the time of the program being written. One such example might be that you need to populate a struct with configuration data that comes from a external file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many other examples, and the one I&amp;rsquo;ll be using today is similar in that I wanted to populate a struct with values provided by a user at runtime, specifically CLI flag values.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-building-blocks-of-reflection&#34;&gt;The building blocks of Reflection&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s consider what are probably the two &lt;em&gt;primary&lt;/em&gt; reflection methods people learn about first when dealing with reflection (these were used in our example code earlier):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;reflect.ValueOf()&lt;/code&gt;: returns a &lt;code&gt;reflect.Value&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;reflect.TypeOf()&lt;/code&gt;: returns a &lt;code&gt;reflect.Type&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Both returned types have a bunch of methods associated with them that are unique to the purpose of those types. So for example, you want a &lt;code&gt;reflect.Value&lt;/code&gt; if you&amp;rsquo;re interested in querying the concrete value, where as &lt;code&gt;reflect.Type&lt;/code&gt; is more useful when you need to know information about the specific type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the use case for getting back a &lt;code&gt;reflect.Type&lt;/code&gt; vs &lt;code&gt;reflect.Value&lt;/code&gt; depends on what you&amp;rsquo;re trying to ascertain at runtime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have either a &lt;code&gt;reflect.Value&lt;/code&gt; or a &lt;code&gt;reflect.Type&lt;/code&gt;, then you can start digging further down into the data that is exposed via these types.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where exploring a real-world use case can be handy, as it helps to clarify &lt;em&gt;why&lt;/em&gt; certain methods on these objects are called (compared to using a more &lt;em&gt;contrived&lt;/em&gt; example).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;package-walk-through-go-flags&#34;&gt;Package Walk-through: Go-Flags&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;ve ever written a CLI program in Go you&amp;rsquo;ll inevitably use its &lt;a href=&#34;https://golang.org/pkg/flag/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;flag&lt;/code&gt;&lt;/a&gt; package. Most people find this package unintuitive and in some cases just downright difficult to work with or to build nice patterns of use from.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This leads people to build their own abstraction patterns on top of the standard library, but from my experience the majority (if not &lt;em&gt;all&lt;/em&gt;) of third-party flag packages are convoluted and confusing to work with. The user experience feels very poor IMHO.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not knocking these packages. They all do very complex things, and solve real problems, and are written by much smarter people than myself. But it doesn&amp;rsquo;t change the fact that rarely do they come across as &amp;lsquo;simple&amp;rsquo; and &amp;lsquo;easy to use&amp;rsquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I wanted to solve the problem of handling flags and commands for a CLI based program in a simple way, that didn&amp;rsquo;t require me to construct a whole bunch of boilerplate code and have to negotiate lots of types.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence I wanted to define a &amp;lsquo;schema&amp;rsquo; of what flags and commands (and flags for those commands) that I was expecting, and to have a package magically populate that struct with the values provided by a user of my program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where utilizing reflection was the only real solution to my problem (if I indeed wanted the user experience to be as simple as possible).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So thus &lt;a href=&#34;https://github.com/integralist/go-flags&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;go-flags&lt;/code&gt;&lt;/a&gt; was born.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s an example of how you would use it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;os&amp;quot;&#xA;&#xA;    &amp;quot;github.com/integralist/go-flags/flags&amp;quot;&#xA;)&#xA;&#xA;type Schema struct {&#xA;    Debug   bool   `short:&amp;quot;d&amp;quot; usage:&amp;quot;enable debug level logs&amp;quot;`&#xA;    Number  int    `short:&amp;quot;n&amp;quot; usage:&amp;quot;a number field&amp;quot;`&#xA;    Message string `short:&amp;quot;m&amp;quot; usage:&amp;quot;a message field&amp;quot;`&#xA;    Foo     struct {&#xA;        AAA string `short:&amp;quot;a&amp;quot; usage:&amp;quot;does A&amp;quot;`&#xA;        BBB string `short:&amp;quot;b&amp;quot; usage:&amp;quot;does B&amp;quot;`&#xA;    }&#xA;    Bar struct {&#xA;        CCC bool `short:&amp;quot;c&amp;quot; usage:&amp;quot;does C&amp;quot;`&#xA;    }&#xA;}&#xA;&#xA;func main() {&#xA;    var s Schema&#xA;&#xA;    err := flags.Parse(&amp;amp;s)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;error parsing schema: %v\n&amp;quot;, err)&#xA;        os.Exit(1)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is very simple and concise from a user&amp;rsquo;s perspective.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see that there are a bunch of top-level, non command specific, flags defined:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-d/-debug&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-n/-number&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-m/-message&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that we utilize &lt;a href=&#34;https://golang.org/ref/spec#Struct_types&#34; target=&#34;_blank&#34;&gt;struct tags&lt;/a&gt; (the backticks that follow the struct field&amp;rsquo;s type) for defining the &amp;lsquo;short&amp;rsquo; flag (while the field name itself is defining the &amp;lsquo;long&amp;rsquo; flag variation) as well as defining the &amp;lsquo;usage&amp;rsquo; description for each flag.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can also see that we&amp;rsquo;ve defined two separate commands (&lt;code&gt;Foo&lt;/code&gt; and &lt;code&gt;Bar&lt;/code&gt;), and each command has its own set of flags:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;foo&lt;/code&gt;: &lt;code&gt;-a/-aaa&lt;/code&gt; (&lt;code&gt;string&lt;/code&gt;), &lt;code&gt;-b/-bbb&lt;/code&gt; (&lt;code&gt;string&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;bar&lt;/code&gt;: &lt;code&gt;-c/-ccc&lt;/code&gt; (&lt;code&gt;bool&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;An example of how a user might then run this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;my_cli_app -debug -n 123 -m &amp;quot;something here&amp;quot; foo -a beepboop -b 666&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;explaining-how-go-flags-uses-reflection&#34;&gt;Explaining how go-flags uses Reflection&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So how exactly does &lt;a href=&#34;https://github.com/integralist/go-flags&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;go-flags&lt;/code&gt;&lt;/a&gt; achieve this magic using reflection?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s step through the code and find out&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not an expert on the &lt;code&gt;reflect&lt;/code&gt; package, nor was a lot of time spent on this package outside getting it functional, so there&amp;rsquo;s likely many improvements that can be made to the code.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll start with the &lt;a href=&#34;https://github.com/Integralist/go-flags/blob/4704c0e/flags/flags.go#L22&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Parse()&lt;/code&gt;&lt;/a&gt; function. Here we can see that the function accepts an argument of type &lt;code&gt;interface{}&lt;/code&gt; which is the empty interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for this is because we want the schema for the flags to be defined by the consumer of this package, and so at runtime we have no idea what that value will look like (hence the use of &lt;code&gt;interface{}&lt;/code&gt; to mean: we&amp;rsquo;ll take any type).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we&amp;rsquo;ve got this unknown value we&amp;rsquo;ll execute the following code to get at the actual value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;v := reflect.Indirect(reflect.ValueOf(s))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see the familiar &lt;code&gt;reflect.ValueOf()&lt;/code&gt; but we have also wrapped it in a call to &lt;code&gt;reflect.Indirect()&lt;/code&gt;, so why do that? Well, the &lt;code&gt;Indirect()&lt;/code&gt; method will dereference the struct pointer to the struct concrete value!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also safe to use &lt;code&gt;Indirect()&lt;/code&gt; because if you give it a non-pointer value it&amp;rsquo;ll just return the value from &lt;code&gt;reflect.ValueOf()&lt;/code&gt;. Don&amp;rsquo;t worry, in just a moment we&amp;rsquo;ll do some validation of the given argument to ensure the user has followed our package instructions and indeed given us a pointer to a struct containing their flag schema.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we acquire a &lt;code&gt;reflect.Type&lt;/code&gt; type from the given argument:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;st := v.Type()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We get the type structure from the &lt;code&gt;reflect.Value&lt;/code&gt; type returned from calling &lt;code&gt;reflect.Indirect()&lt;/code&gt;, and we do this because later on we&amp;rsquo;ll pass it into a function called &lt;a href=&#34;https://github.com/Integralist/go-flags/blob/4704c0e/flags/flags.go#L160&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;IterFields&lt;/code&gt;&lt;/a&gt; which iterates over the user&amp;rsquo;s schema struct. We pass it into that function because within there we&amp;rsquo;ll try to get the struct&amp;rsquo;s individual fields as a &lt;code&gt;reflect.StructField&lt;/code&gt; (I&amp;rsquo;ll explain why we want that later).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now it&amp;rsquo;s at this point we do some runtime type validation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;if v.Kind() != reflect.Struct {&#xA;  return ErrWrongType&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re expecting a struct and there&amp;rsquo;s no point trying to go any further with something that&amp;rsquo;s &lt;em&gt;not&lt;/em&gt; a struct, so we short-circuit the program if we&amp;rsquo;re given anything unexpected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, at this point of our package we have a few stages that involve, among many things, iterating the given struct (we use a custom iterator function called &lt;code&gt;IterFields&lt;/code&gt; and we pass it a callback function to execute for each &amp;lsquo;field&amp;rsquo; in the given struct).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Here are the stages at a high-level:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;iterate over the top level fields of the user provided struct, and dynamically create flags.&lt;/li&gt;&#xA;&lt;li&gt;parse the flag values the user of the CLI program have provided (using the flags our package has now dynamically generated).&lt;/li&gt;&#xA;&lt;li&gt;iterate over the top level fields of the user provided struct, and populate the fields with the parsed flag values.&lt;/li&gt;&#xA;&lt;li&gt;identify the command the user provided when running the CLI program (e.g. &lt;code&gt;foo&lt;/code&gt; or &lt;code&gt;bar&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;parse the flag values the user provided after specifying the command.&lt;/li&gt;&#xA;&lt;li&gt;dynamically create a &lt;code&gt;flag.FlagSet&lt;/code&gt; for the command.&lt;/li&gt;&#xA;&lt;li&gt;parse the flagset values the user provided (using the flagset our package has now dynamically generated).&lt;/li&gt;&#xA;&lt;li&gt;iterate over the command fields of the user provided struct, and populate the fields with the parsed flagset values.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Now we understand the general steps taken, we can dig into each of those and understand what reflection work needs to be carried out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I won&amp;rsquo;t be discussing the general code logic, just picking out the bits related to reflection. So if you want to understand the full go-flags implementation, then I recommend you read through the code base in its entirety after finishing this post.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if I was working with Go 2.0 then I&amp;rsquo;d have access to generics and parts of this code could be reduced/simplified. Hello future readers who are lucky enough to have Go 2.0.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;As the majority of these steps are related to iterating over the user provided struct, let&amp;rsquo;s start with the &lt;code&gt;IterFields&lt;/code&gt; function that enables that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First thing we do in &lt;code&gt;IterFields()&lt;/code&gt; is we call &lt;code&gt;.NumField()&lt;/code&gt; on the &lt;code&gt;reflect.Value&lt;/code&gt;, which gives us back the number of fields the struct contains.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This will panic if the &lt;code&gt;reflect.Kind()&lt;/code&gt; is not a &lt;code&gt;reflect.Struct&lt;/code&gt; type, hence why at the beginning of our &lt;code&gt;Parse()&lt;/code&gt; function we do that validation there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We could have moved the check for a struct down into the &lt;code&gt;IterFields()&lt;/code&gt; function but then we&amp;rsquo;d end up doing extra unnecessary logic processing only to have to just stop the program any way (so best to short circuit the code as soon as possible).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we have the number of struct fields, we&amp;rsquo;ll create a loop for that number and we&amp;rsquo;ll use the incrementing &lt;code&gt;i&lt;/code&gt; value to access each individual struct field by calling &lt;code&gt;.Field()&lt;/code&gt; on the &lt;code&gt;v&lt;/code&gt; variable&amp;rsquo;s &lt;code&gt;reflect.Value&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll find that when you call methods on a &lt;code&gt;reflect.Value&lt;/code&gt; type you&amp;rsquo;ll likely end up with &amp;hellip;another &lt;code&gt;reflect.Value&lt;/code&gt; type!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;for i := 0; i &amp;lt; v.NumField(); i++ {&#xA;  field := v.Field(i)&#xA;&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next we call the &lt;code&gt;.Field()&lt;/code&gt; method again but this time on the &lt;code&gt;reflect.Type&lt;/code&gt; type. The reason we do this is because (as I mentioned earlier) we want a &lt;code&gt;reflect.StructField&lt;/code&gt; type (which is what the &lt;code&gt;.Field()&lt;/code&gt; call will give us) so we can inspect it later on in the callback function and parse out the &amp;lsquo;tags&amp;rsquo; assigned to the current struct field.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We have at this point a if/else condition which I&amp;rsquo;m going to skip over the &lt;code&gt;if&lt;/code&gt; block briefly and move onto discussing the &lt;code&gt;else&lt;/code&gt; block which states:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;if !recurse &amp;amp;&amp;amp; field.CanSet() {&#xA;    callback(field, sf)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll see we call &lt;code&gt;.CanSet()&lt;/code&gt; on the &lt;code&gt;field&lt;/code&gt; variable which (as noted earlier) is actually a &lt;code&gt;reflect.Value&lt;/code&gt; type. The reason we do this is because one of the given callback functions will attempt to set a value onto the struct field and that is only valid if the struct field is public (i.e. &lt;em&gt;exported&lt;/em&gt;) otherwise it would panic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s jump back up to the &lt;code&gt;if&lt;/code&gt; statement, in there we&amp;rsquo;re checking the condition:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;if field.Kind() == reflect.Struct {&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is a similar check to what we did at the start of the &lt;code&gt;Parse()&lt;/code&gt; function, so why are we doing it again? Well, this time (as we iterate over the user&amp;rsquo;s schema struct and look at each field) we might discover one of the fields is itself a struct! So we want to also iterate over the nested struct&amp;rsquo;s fields looking for flag information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All the code within this &lt;code&gt;if&lt;/code&gt; block is effectively the same as what came before it with regards to getting access to the underlying struct &amp;lsquo;value&amp;rsquo; that is assigned to the current struct&amp;rsquo;s field, and then looping over that nested structs own fields.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We could have done this with recursion but then it makes the &lt;code&gt;IterFields()&lt;/code&gt; function more complex and as I was designing go-flags to work with only one level of nesting supported it wasn&amp;rsquo;t worth the effort to implementing a strict recursive function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That said, there is one aspect of the &lt;code&gt;if&lt;/code&gt; block we should look at which is the &lt;em&gt;nested&lt;/em&gt; &lt;code&gt;if&lt;/code&gt; block. The nested &lt;code&gt;if&lt;/code&gt; block is what actually does the looping over the nested struct&amp;rsquo;s fields, and it does this by first getting at the nested struct concrete value (as I mentioned a moment ago).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To get at that struct value we do:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;reflect.TypeOf(field.Interface())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so this needs some explaining! Firstly, we call &lt;code&gt;.Interface()&lt;/code&gt; on the &lt;code&gt;field&lt;/code&gt; variable (which is a &lt;code&gt;reflect.Value&lt;/code&gt; type) and then we pass that &amp;lsquo;result&amp;rsquo; to &lt;code&gt;reflect.TypeOf()&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;.Interface()&lt;/code&gt; method will get the underlying concrete value as an empty interface (i.e. &lt;code&gt;interface{}&lt;/code&gt;) type, and so that&amp;rsquo;s what we pass to &lt;code&gt;reflect.TypeOf()&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we use &lt;code&gt;.Interface()&lt;/code&gt; first is because if we had just passed the &lt;code&gt;field&lt;/code&gt; variable into &lt;code&gt;reflect.TypeOf()&lt;/code&gt;, then we would have gotten &lt;code&gt;reflect.Value&lt;/code&gt; as the type (and that&amp;rsquo;s no use to us! we want the struct type).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So why did we need the struct type? Well, after we start iterating over the nested struct&amp;rsquo;s fields, we again need to get a &lt;code&gt;reflect.StructField&lt;/code&gt; so that when we execute the given callback function it&amp;rsquo;ll be able to parse any &amp;lsquo;tags&amp;rsquo; found on the nested struct fields.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point in time we&amp;rsquo;ve explained some key bits as far as looping &lt;em&gt;safely&lt;/em&gt; over the user&amp;rsquo;s struct, so let&amp;rsquo;s go back to what we do in some of the &amp;lsquo;callback&amp;rsquo; functions that get executed for each struct field.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing we do is access the struct field&amp;rsquo;s tags, and we do this by calling &lt;code&gt;.Tag.Get()&lt;/code&gt; on the &lt;code&gt;reflect.StructField&lt;/code&gt; type. So in go-flags we ask users to add struct tags like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;short:&amp;quot;...&amp;quot; usage:&amp;quot;...&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s two tags &amp;lsquo;short&amp;rsquo; and &amp;lsquo;usage&amp;rsquo;. So if I want the &amp;lsquo;short&amp;rsquo; tag I&amp;rsquo;d call &lt;code&gt;.Tag.Get(&amp;quot;short&amp;quot;)&lt;/code&gt; and if I want the &amp;lsquo;usage&amp;rsquo; tag I&amp;rsquo;d call &lt;code&gt;.Tag.Get(&amp;quot;usage&amp;quot;)&lt;/code&gt;. Nice and simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When it comes to setting the field values we have to check the kind of the field (remember this is a &lt;code&gt;reflect.Value&lt;/code&gt; type). The following switch statement demonstrates this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;switch field.Kind() {&#xA;case reflect.Bool:&#xA;    if b, ok := getter.Get().(bool); ok {&#xA;        field.Set(reflect.ValueOf(b))&#xA;    }&#xA;case reflect.Int:&#xA;    if i, ok := getter.Get().(int); ok {&#xA;        field.Set(reflect.ValueOf(i))&#xA;    }&#xA;case reflect.String:&#xA;    if s, ok := getter.Get().(string); ok {&#xA;        field.Set(reflect.ValueOf(s))&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The call to &lt;code&gt;.Kind()&lt;/code&gt; returns a &lt;code&gt;reflect.Kind&lt;/code&gt; type, which is an integer iota that maps constants to a numerical value for easier comparison. Hence each case is a check against some of those constants like &lt;code&gt;reflect.Bool&lt;/code&gt;, &lt;code&gt;reflect.Int&lt;/code&gt; and &lt;code&gt;reflect.String&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we know what type the field is we type assert the flag value to the relevant type and then call &lt;code&gt;.Set()&lt;/code&gt; on the field. You&amp;rsquo;ll notice that we can&amp;rsquo;t just pass the value into the &lt;code&gt;.Set()&lt;/code&gt; method as we need to provide an argument of type &lt;code&gt;reflect.Value&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To fix that we call &lt;code&gt;reflect.ValueOf()&lt;/code&gt; and pass it the value we&amp;rsquo;re trying to set, and then pass that resulting &lt;code&gt;reflect.Value&lt;/code&gt; type into &lt;code&gt;.Set()&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, that&amp;rsquo;s it! There is &lt;em&gt;sooooo&lt;/em&gt; much more to reflection than what I have had time to describe in this post, but hopefully this has been enough to help you in the future if you ever stumble across a need for reflection.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing I would say before I go is: avoid reflection wherever possible. It&amp;rsquo;s a nightmare to work with and although we can code defensively and get back some runtime safety, that&amp;rsquo;s still no comparison to compile time safety. There&amp;rsquo;s also a performance cost to runtime reflection that can&amp;rsquo;t be ignored.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So do please think twice before reaching for reflection.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-reflection/</guid>
      <link>https://www.integralist.co.uk/posts/go-reflection/</link>
      <pubDate>Mon, 17 Aug 2020 00:00:00 +0000</pubDate>
      <title>Reflection in Go</title>
    </item>
    <item>
      <description>&lt;p&gt;When writing software you will inevitably need to choose an external code library to assist you with some specific feature or behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;re also likely to discover that there are many tools available that claim to solve the same problem. So how do you choose which one to use?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should carefully compare the value of each individual tool that is under consideration, and to do &lt;em&gt;that&lt;/em&gt; we typically utilize a comparative table.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;comparison-matrix&#34;&gt;Comparison Matrix&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A comparison matrix table should take into consideration the following properties:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Activeness&lt;/strong&gt;: is the repo/source code actively maintained (e.g. features, bug fixes etc).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Dependencies&lt;/strong&gt;: how large is the dependency graph.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Design&lt;/strong&gt;: does the interface follow golang syntax/language best patterns.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: is there sufficient documentation to support the code.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;: is it part of a larger ecosystem and is it easy to extend.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt;: which implementation is more performant.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Popularity&lt;/strong&gt;: which tool is more popular (based on GitHub stars, so not scientific!).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Stability&lt;/strong&gt;: how buggy is the software (based on GitHub issues, so not scientific!). †&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Suitability&lt;/strong&gt;: how effective is it (e.g. what core APIs/features does it provide).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Usability&lt;/strong&gt;: how easy to use it is (warning: this is subjective).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† stability: we can&amp;rsquo;t really judge the quality of issues raised, nor can we suggest that more issues is an indicator of poorly written software (e.g. a more popular tool is likely to have a larger number of issues raised compared to a tool with very few users).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But we can at least compare the number of issues that have been closed vs those that are left open and stale (e.g. a code base may be very active and still have poor user engagement by ignoring opened issues).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although again, this is flawed because a code base with a much higher number of users (and thus a much higher number of issues raised) may not be able to review issues as quickly as a code base with very few users.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;emoji-key&#34;&gt;Emoji Key&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We will use the following emojis to identify comparative outcomes:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;✅: clear winner&lt;/li&gt;&#xA;&lt;li&gt;❌: clear loser&lt;/li&gt;&#xA;&lt;li&gt;⚖️: balanced results&lt;/li&gt;&#xA;&lt;li&gt;🗑: no winner/no loser&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I will sometimes mark both tools as neither ‘winner’ or ‘loser’ due to the comparative value not necessarily being indicative of either. For example, the data point might just be ‘of interest’ (such as the date of when the project started).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;&lt;/th&gt;&#xA;&lt;th&gt;Tool A&lt;/th&gt;&#xA;&lt;th&gt;Tool B&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Property A&lt;/td&gt;&#xA;&lt;td&gt;✅&lt;/td&gt;&#xA;&lt;td&gt;❌&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Property B&lt;/td&gt;&#xA;&lt;td&gt;⚖️&lt;/td&gt;&#xA;&lt;td&gt;⚖️&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Property C&lt;/td&gt;&#xA;&lt;td&gt;🗑&lt;/td&gt;&#xA;&lt;td&gt;🗑&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h3 id=&#34;winner-tool-a&#34;&gt;Winner: Tool A&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We would have these results stored inside some kind of shared document for historical purposes, and once a winner is identified, then we should declare what the proposed steps are for integrating the chosen tool (as that in itself can sometimes determine whether the tool is the winner or not, depending on deadlines and/or &amp;lsquo;time to market&amp;rsquo; etc).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/software-comparison/</guid>
      <link>https://www.integralist.co.uk/posts/software-comparison/</link>
      <pubDate>Sat, 18 Jul 2020 00:00:00 +0000</pubDate>
      <title>Tips for Comparing Code Libraries</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;what-is-rate-limiting&#34;&gt;What is Rate Limiting?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Rate Limiting is a technique used to control the rate of requests received.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It exists to help online services to stay up and running even when clients of the service are issuing lots of requests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think of an API such as the &lt;a href=&#34;https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting&#34; target=&#34;_blank&#34;&gt;GitHub API&lt;/a&gt;. If they didn&amp;rsquo;t rate limit their clients, then it&amp;rsquo;s very possible a single client could consume most of their resources (either accidentally or intentionally, i.e. a &amp;ldquo;bad actor&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;problems-with-rate-limiting&#34;&gt;Problems with Rate Limiting&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are two key issues that I needed to address for my employer. The first is very specific to the needs we were trying to solve, and the other is a general issue&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;our service is public, not private.&lt;/li&gt;&#xA;&lt;li&gt;avoid overloading our internal infrastructure.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s consider the first point: most exposed APIs will expect a client to provide a &amp;lsquo;key&amp;rsquo; in order to access the API (this allows the API service to keep a track of individual clients and to ensure they aren&amp;rsquo;t being overly aggressive with their requests).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But I work for a well known online publisher, and so our customers are public users visiting our public website, which means we can&amp;rsquo;t rate limit using a &amp;lsquo;key&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because we don&amp;rsquo;t know who our clients are, and so we can&amp;rsquo;t expect them to have signed up to get a key to access our content (unless our content was sat behind a paywall, which it isn&amp;rsquo;t).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means we have to identify clients another way. The typical approach here is to identify a client by their IP address.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Identifying a client by an IP is problematic for rate limiting because you potentially will end up grouping together multiple clients who all happen to be using the same IP address (e.g. a college campus).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what can we do to address these two issues?&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#identify-clients-more-granularly&#34;&gt;Identify clients more granularly&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#get-your-cdn-to-help&#34;&gt;Get your CDN to help&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;identify-clients-more-granularly&#34;&gt;Identify clients more granularly&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The problem with IP identification is that it&amp;rsquo;s not granular enough. To workaround this issue we create a fingerprint of the client that&amp;rsquo;s actually a hash built from multiple contextual pieces of data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;host&amp;gt;:&amp;lt;path&amp;gt;:&amp;lt;method&amp;gt;:&amp;lt;client-ip&amp;gt;:&amp;lt;user-agent&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This means we ultimately are rate limiting clients on a &amp;lsquo;path&amp;rsquo; basis, meaning a client can request &lt;code&gt;/foo&lt;/code&gt; enough to be rate limited for that path but still be allowed to access &lt;code&gt;/bar&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But this doesn&amp;rsquo;t help us with web scrapers and fuzzers who present a potential Denial of Service (DoS) attack by hitting &lt;em&gt;multiple&lt;/em&gt; endpoints at a very high rate (this is because the count for a single path could be low while their overall crawling impact could be much larger and damaging).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This forces us to define two types of clients:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Standard&lt;/li&gt;&#xA;&lt;li&gt;Broad&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;standard&amp;rsquo; clients are those we described originally (they hit a single endpoint at a high rate). An example of this are pentesters trying to compromise a sign-in page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;broad&amp;rsquo; clients are those who have a less granular fingerprint (specifically &lt;code&gt;&amp;lt;client-ip&amp;gt;:&amp;lt;user-agent&amp;gt;&lt;/code&gt;), and where we cross reference them against a list of known pentesting/scraper/fuzzer tools.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;get-your-cdn-to-help&#34;&gt;Get your CDN to help&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The problem we had was that our internal services were struggling to handle the volume of uncacheable requests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What would be better is if we could leverage the scale of our CDN provider (&lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt;) rather than have our internal infrastructure front the burden.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this we needed a way for the CDN to be able to identify a client as one that should be rate limited. But we didn&amp;rsquo;t have enough programmatic access with Fastly to achieve this (their infrastructure is designed around &lt;a href=&#34;https://varnish-cache.org/&#34; target=&#34;_blank&#34;&gt;Varnish&lt;/a&gt; which uses a specialized DSL called &lt;a href=&#34;https://book.varnish-software.com/4.0/chapters/VCL_Basics.html&#34; target=&#34;_blank&#34;&gt;VCL&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I won&amp;rsquo;t explain &lt;em&gt;why&lt;/em&gt; we didn&amp;rsquo;t have enough programmatic access with Fastly, because it requires an understanding of Fastly and their services, which is outside the scope of this post.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Fastly does have a beta product called &lt;a href=&#34;https://www.fastly.com/blog/join-the-beta-new-serverless-compute-environment-at-the-edge&#34; target=&#34;_blank&#34;&gt;compute@edge&lt;/a&gt; but it&amp;rsquo;s still very early stages and they don&amp;rsquo;t recommend their customers use it for production workloads.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With the above understanding clear in our minds, let&amp;rsquo;s take a look at the architecture I ended up designing/implementing:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Existing proxy tracks clients via Redis.&lt;/li&gt;&#xA;&lt;li&gt;New HTTP service (written in Go):&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Periodically scans Redis.&lt;/li&gt;&#xA;&lt;li&gt;Identifies if client should be rate limited.&lt;/li&gt;&#xA;&lt;li&gt;Updates Fastly &amp;lsquo;edge dictionary&amp;rsquo; via Fastly API.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Fastly CDN checks &amp;lsquo;edge dictionary&amp;rsquo; and rejects clients as necessary.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Visually this looks something like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/ratelimit.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/ratelimit.png&#34; alt=&#34;ratelimit&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;Two things worth clarifying in the above architecture diagram&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We&amp;rsquo;ll attempt to serve a cached response from the CDN otherwise we&amp;rsquo;ll attempt to serve stale (if available), before finally falling back to a synthetic &lt;code&gt;429 Too Many Requests&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;The &amp;ldquo;Perimeter&amp;rdquo; service directly behind the CDN was a pre-existing custom built reverse proxy (only slightly modified for the purpose of putting clients into redis).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;downsides&#34;&gt;Downsides&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The biggest downside is that there is a delay in applying rate limits, as processing data isn’t happening at runtime (i.e. the &amp;lsquo;Rate Control&amp;rsquo; service is decoupled from the perimeter proxy).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This additionally introduces some complexity in the sense that we have to limit requests per &amp;lsquo;minute&amp;rsquo; rather than the more traditional &amp;lsquo;request per second&amp;rsquo; (as we need to allow the external service time to process data).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Subsequently this design will allow more requests through to our internal infrastructure before rate limiting will be applied. In practice this hasn&amp;rsquo;t been an issue for us, but it&amp;rsquo;s worth calling out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, although this works well for our purposes I appreciate it is not a perfect solution, and is merely a tourniquet.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so let&amp;rsquo;s review the benefits of this design&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Verifies if a client requires rate limit restriction.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Then notifies CDN to action this behaviour.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Provides DoS level protection.&lt;/li&gt;&#xA;&lt;li&gt;Implements granular level of client identification.&lt;/li&gt;&#xA;&lt;li&gt;Supports identification/blocking of common scrapers/fuzzers:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://sqlmap.org&#34; target=&#34;_blank&#34;&gt;http://sqlmap.org&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://scrapy.org&#34; target=&#34;_blank&#34;&gt;https://scrapy.org&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://simplepie.org&#34; target=&#34;_blank&#34;&gt;https://simplepie.org&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://nutch.apache.org&#34; target=&#34;_blank&#34;&gt;https://nutch.apache.org&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/ffuf/ffuf&#34; target=&#34;_blank&#34;&gt;https://github.com/ffuf/ffuf&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://tools.kali.org/web-applications/wfuzz&#34; target=&#34;_blank&#34;&gt;https://tools.kali.org/web-applications/wfuzz&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Supports reduction of requests handled by our own infrastructure.&lt;/li&gt;&#xA;&lt;li&gt;Supports reduction of additional latency.&lt;/li&gt;&#xA;&lt;li&gt;Avoids overloading upstream proxy(s) responsibility.&lt;/li&gt;&#xA;&lt;li&gt;Provides CLI tooling to:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Clear a rate limited client from the Fastly edge dictionary.&lt;/li&gt;&#xA;&lt;li&gt;Toggle on/off rate limiting at the edge.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although not done yet, I intend on building an internal UI service for &amp;lsquo;Rate Control&amp;rsquo; that will make interfacing with the various components easier (inc. all features currently present in the CLI).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;example-code&#34;&gt;Example Code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see some example VCL code to understand the CDN edge implementation a bit better&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for brevity I&amp;rsquo;ve removed chunks of logic so we can more easily focus in on the &amp;lsquo;control flow&amp;rsquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub ratelimit_trigger {&#xA;  // client is rate limited, so attempt to find cached version of the content&#xA;  //&#xA;  set req.http.X-Reject = &amp;quot;true&amp;quot;;&#xA;  return(lookup);&#xA;}&#xA;&#xA;sub ratelimit_recv {&#xA;  // client_key generates a key from the contextual data we&#39;re looking for&#xA;  //&#xA;  set var.client_hash = digest.hash_sha1(var.client_key);&#xA;&#xA;  if (table.lookup(ratelimit, var.client_hash) == &amp;quot;true&amp;quot;) {&#xA;    call ratelimit_trigger;&#xA;  }&#xA;&#xA;  // if we&#39;re unable to find the current key, then before we allow the normal request flow to continue&#xA;  // we&#39;ll first check if we can find a &#39;bad actor&#39; (e.g. web scraper/fuzzer) in the rate limit table&#xA;  //&#xA;  // NOTE: it&#39;s at this point we&#39;d change the client_key and regenerate the client_hash.&#xA;  //&#xA;  if (table.lookup(ratelimit, var.client_hash) == &amp;quot;true&amp;quot;) {&#xA;    call ratelimit_trigger;&#xA;  }&#xA;}&#xA;&#xA;sub ratelimit_miss {&#xA;  // we were unable to find cached content, so move to vcl_error&#xA;  // where we&#39;ll attempt to serve stale if it exists, otherwise&#xA;  // we&#39;ll serve a synthetic &#39;429 Too Many Requests&#39;&#xA;  //&#xA;  error 601;&#xA;}&#xA;&#xA;sub ratelimit_error {&#xA;  if (obj.status == 601) {&#xA;    if (stale.exists) {&#xA;      return(deliver_stale);&#xA;    }&#xA;&#xA;    set obj.status = 429;&#xA;    set obj.response = &amp;quot;Too Many Requests&amp;quot;;&#xA;    set obj.http.Content-Type = &amp;quot;text/html&amp;quot;;&#xA;    synthetic {&amp;quot;&amp;lt;h1&amp;gt;Too Many Requests&amp;lt;/h1&amp;gt;&amp;quot;};&#xA;    return(deliver);&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code would typically be a separate code file which we&amp;rsquo;d include in our standard VCL file and then call within the relevant state subroutines&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;again I&amp;rsquo;ve omitted chunks of code for the sake of brevity.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;include &amp;quot;rate_limiting&amp;quot;&#xA;&#xA;sub vcl_recv {&#xA;  unset req.http.X-Reject;&#xA;&#xA;  call ratelimit_recv;&#xA;}&#xA;&#xA;sub vcl_miss {&#xA;  if (req.http.X-Reject == &amp;quot;true&amp;quot;) {&#xA;    call ratelimit_miss;&#xA;  }&#xA;}&#xA;&#xA;sub vcl_error {&#xA;  call ratelimit_error;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/rate-limiting/</guid>
      <link>https://www.integralist.co.uk/posts/rate-limiting/</link>
      <pubDate>Wed, 08 Jul 2020 00:00:00 +0000</pubDate>
      <title>Rate Limiting at the CDN Edge</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many version control systems, but &lt;a href=&#34;https://git-scm.com/&#34; target=&#34;_blank&#34;&gt;git&lt;/a&gt; is undoubtedly the most popular, and regularly used, thanks to online social platforms such as &lt;a href=&#34;https://www.github.com/&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt; and &lt;a href=&#34;https://gitlab.com/&#34; target=&#34;_blank&#34;&gt;GitLab&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Yet, it is a tool that is still vastly misunderstood and feared. In this post I aim to take a look at some of the internal moving parts of git, primarily what&amp;rsquo;s inside the &lt;code&gt;.git&lt;/code&gt; directory (inc the various subdirectories and files).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My hope is that by better understanding how git works, and the concepts it is built upon, readers will feel more empowered and confident when working with git (especially when they have issues and would normally be unsure of what to do).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this article isn&amp;rsquo;t an introduction to git, and does presume that the reader is familiar with (i.e. a user of) git.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;general-concept&#34;&gt;General Concept&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I wanted to take a quick moment just to clarify the terminology associated with the general concepts of how git works (so we&amp;rsquo;re all on the same page):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Working Directory&lt;/strong&gt;: your project files.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Staging Area&lt;/strong&gt;: a file that tracks the changes to your project files.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Repository&lt;/strong&gt;: the location where your project files are stored.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;these bullet points are just summarizations, but I would like to extend upon it slightly in that: your &amp;lsquo;working directory&amp;rsquo; can &lt;em&gt;change&lt;/em&gt; depending on what &amp;lsquo;version&amp;rsquo; of the project you have &amp;lsquo;checked out&amp;rsquo; from the git repository (i.e. this is what happens when you change your &amp;lsquo;branch&amp;rsquo; with &lt;code&gt;git checkout &amp;lt;branch_name&amp;gt;&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So for example, commands like &lt;code&gt;git add&lt;/code&gt; will copy objects from the working directory into the staging area (aka the &amp;lsquo;index&amp;rsquo;), while &lt;code&gt;git reset&lt;/code&gt; will &lt;em&gt;remove&lt;/em&gt; objects from the staging area.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A command such as &lt;code&gt;git diff&lt;/code&gt; compares your working directory to your staging area, while using the &lt;code&gt;--staged&lt;/code&gt; flag will change this behaviour such that git will compare your staging area to your actual repository state.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;subcommands-porcelain-and-plumbing&#34;&gt;Subcommands: Porcelain and Plumbing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The git version control system wasn&amp;rsquo;t initially designed to be a user-friendly interface, and so alongside the more commonly used subcommands are commands that can carry out very low-level operations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This has resulted in much confusion around what commands are intended for use by general users and which commands exist for the purpose of internal use.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although used internally, the low-level subcommands are also typically used by systems that require such granular operational control.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;git&lt;/code&gt; subcommands are generally split into one of two groups:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;Porcelain&lt;/em&gt;: the user-friendly interface (e.g. &lt;code&gt;git checkout&lt;/code&gt;, &lt;code&gt;git pull&lt;/code&gt; etc.)&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Plumbing&lt;/em&gt;: low-level interface (e.g. &lt;code&gt;git cat-file&lt;/code&gt;, &lt;code&gt;git rev-parse&lt;/code&gt; etc.)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;git-subcommands&#34;&gt;Git Subcommands&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Below is a list of the &lt;code&gt;git&lt;/code&gt; subcommands (as of git version &lt;code&gt;2.22.0&lt;/code&gt;), and knowing which are meant to be &amp;lsquo;porcelain&amp;rsquo; and which are meant to be &amp;lsquo;plumbing&amp;rsquo; can be difficult.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;$ man git-&amp;lt;tab&amp;gt;&#xA;&#xA;git-add                       git-commit-tree               git-fsck                      &#xA;git-am                        git-config                    git-fsck-objects              &#xA;git-annotate                  git-count-objects             git-gc                        &#xA;git-apply                     git-credential                git-get-tar-commit-id         &#xA;git-archimport                git-credential-cache          git-grep                      &#xA;git-archive                   git-credential-cache--daemon  git-gui                       &#xA;git-bisect                    git-credential-store          git-hash-object               &#xA;git-blame                     git-cvsexportcommit           git-help                      &#xA;git-branch                    git-cvsimport                 git-http-backend              &#xA;git-bundle                    git-cvsserver                 git-http-fetch                &#xA;git-cat-file                  git-daemon                    git-http-push                 &#xA;git-check-attr                git-describe                  git-imap-send                 &#xA;git-check-ignore              git-diff                      git-index-pack                &#xA;git-check-mailmap             git-diff-files                git-init                      &#xA;git-check-ref-format          git-diff-index                git-init-db                   &#xA;git-checkout                  git-diff-tree                 git-instaweb                  &#xA;git-checkout-index            git-difftool                  git-interpret-trailers        &#xA;git-cherry                    git-fast-export               git-log                       &#xA;git-cherry-pick               git-fast-import               git-ls-files                  &#xA;git-citool                    git-fetch                     git-ls-remote                 &#xA;git-clean                     git-fetch-pack                git-ls-tree                   &#xA;git-clone                     git-filter-branch             git-mailinfo                  &#xA;git-column                    git-fmt-merge-msg             git-mailsplit                 &#xA;git-commit                    git-for-each-ref              git-merge                     &#xA;git-commit-graph              git-format-patch              git-merge-base                &#xA;git-merge-file                git-rebase                    git-show-index&#xA;git-merge-index               git-receive-pack              git-show-ref&#xA;git-merge-one-file            git-reflog                    git-stage&#xA;git-merge-tree                git-remote                    git-stash&#xA;git-mergetool                 git-remote-ext                git-status&#xA;git-mergetool--lib            git-remote-fd                 git-stripspace&#xA;git-mktag                     git-remote-testgit            git-submodule&#xA;git-mktree                    git-repack                    git-svn&#xA;git-multi-pack-index          git-replace                   git-symbolic-ref&#xA;git-mv                        git-request-pull              git-tag&#xA;git-name-rev                  git-rerere                    git-unpack-file&#xA;git-notes                     git-reset                     git-unpack-objects&#xA;git-p4                        git-rev-list                  git-update-index&#xA;git-pack-objects              git-rev-parse                 git-update-ref&#xA;git-pack-redundant            git-revert                    git-update-server-info&#xA;git-pack-refs                 git-rm                        git-upload-archive&#xA;git-parse-remote              git-send-email                git-upload-pack&#xA;git-patch-id                  git-send-pack                 git-var&#xA;git-prune                     git-sh-i18n                   git-verify-commit&#xA;git-prune-packed              git-sh-i18n--envsubst         git-verify-pack&#xA;git-pull                      git-sh-setup                  git-verify-tag&#xA;git-push                      git-shell                     git-web--browse&#xA;git-quiltimport               git-shortlog                  git-whatchanged&#xA;git-range-diff                git-show                      git-worktree&#xA;git-read-tree                 git-show-branch               git-write-tree&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But there &lt;em&gt;is&lt;/em&gt; a way to find out! Currently the &lt;code&gt;man git&lt;/code&gt; page describes which commands are intended as porcelain and which are plumbing. Simple search for &lt;code&gt;GIT COMMANDS&lt;/code&gt; and you&amp;rsquo;ll find the two groupings.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My own generalized way of making a distinction is to consider the day-to-day subcommands I use (e.g. &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git diff&lt;/code&gt;) as being porcelain, while the more esoteric subcommands (e.g. &lt;code&gt;git fsck&lt;/code&gt;, &lt;code&gt;git multi-pack-index&lt;/code&gt;) as being more plumbing orientated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In practice it doesn&amp;rsquo;t &lt;em&gt;really&lt;/em&gt; matter which subcommands are porcelain and which are plumbing. If there&amp;rsquo;s a subcommand you feel you need to use, then go ahead and use it. My personal perspective on this is: if you&amp;rsquo;re ever unsure of what it is you&amp;rsquo;re doing you&amp;rsquo;re unlikely to use a subcommand.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most users do not diverge from the well trodden path of: &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;, &lt;code&gt;git pull&lt;/code&gt;, &lt;code&gt;git push&lt;/code&gt;, &lt;code&gt;git diff&lt;/code&gt; (with an occasional &lt;code&gt;git rebase&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s interesting about the plumbing subcommands is that some of them are used internally by git when you&amp;rsquo;re calling the porcelain subcommands (e.g. &lt;code&gt;git read-tree&lt;/code&gt;, &lt;code&gt;git update-index&lt;/code&gt;, &lt;code&gt;git update-ref&lt;/code&gt; will be called by other porcelain commands such as &lt;code&gt;git add&lt;/code&gt; or &lt;code&gt;git commit&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although we&amp;rsquo;ll be looking at a couple of plumbing commands in this article, I&amp;rsquo;ll refer you to the &lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Internals-Git-Objects&#34; target=&#34;_blank&#34;&gt;git book&lt;/a&gt; for a look at the different plumbing commands available and how they&amp;rsquo;re used.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;the-git-directory&#34;&gt;The &lt;code&gt;.git&lt;/code&gt; directory&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you start a new project that you want to use version control for, you&amp;rsquo;ll typically run the &lt;code&gt;git init&lt;/code&gt; subcommand:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git init [dir]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Most people will know that there is now a &lt;code&gt;.git&lt;/code&gt; directory created in the root of your project directory, but that&amp;rsquo;s about where their understanding of things stop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see what&amp;rsquo;s initially inside the &lt;code&gt;.git&lt;/code&gt; directory of a new project&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ tree .git/&#xA;&#xA;.git/&#xA;├── HEAD&#xA;├── config&#xA;├── description&#xA;├── hooks&#xA;│   ├── applypatch-msg.sample&#xA;│   ├── commit-msg.sample&#xA;│   ├── fsmonitor-watchman.sample&#xA;│   ├── post-update.sample&#xA;│   ├── pre-applypatch.sample&#xA;│   ├── pre-commit.sample&#xA;│   ├── pre-push.sample&#xA;│   ├── pre-rebase.sample&#xA;│   ├── pre-receive.sample&#xA;│   ├── prepare-commit-msg.sample&#xA;│   └── update.sample&#xA;├── info&#xA;│   └── exclude&#xA;├── objects&#xA;│   ├── info&#xA;│   └── pack&#xA;└── refs&#xA;    ├── heads&#xA;    └── tags&#xA;&#xA;8 directories, 15 files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so there&amp;rsquo;s some important directories and files here that we need to learn a bit about in order to appreciate how git works.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not going to explain &lt;em&gt;every&lt;/em&gt; file and directory, only those necessary to understand the fundamentals.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here are some interesting ones:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;HEAD&lt;/code&gt;: contains a pointer to the tip of the &lt;em&gt;current&lt;/em&gt; branch.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;config&lt;/code&gt;: contains project-specific configuration options.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;info&lt;/code&gt;: contains a &lt;em&gt;global&lt;/em&gt; exclude file †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;objects&lt;/code&gt;: contains four types of &amp;lsquo;objects&amp;rsquo; (commit, tree, blob, tag).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;refs&lt;/code&gt;: contains pointers to &amp;lsquo;commit&amp;rsquo; objects.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this is separate from a local user&amp;rsquo;s &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;references-and-objects&#34;&gt;References and Objects&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The two most important concepts in git are: &lt;strong&gt;references&lt;/strong&gt; and &lt;strong&gt;objects&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, your branches, tags and remotes are all references to commits. While your commits are objects, your files are objects, your directories are objects.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;references&#34;&gt;References&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Git is built upon the simple premise of using &amp;lsquo;pointers&amp;rsquo; to data, and these pointers are typically referred to as &amp;lsquo;references&amp;rsquo; (or &amp;lsquo;refs&amp;rsquo; for short).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is what the &lt;code&gt;.git/refs&lt;/code&gt; directory stores: references.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As I mentioned earlier, these references all point to a &amp;lsquo;commit&amp;rsquo; object&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;remote    branch     tag&#xA;  |          |        |&#xA;  |          |        |&#xA;  |          V        |&#xA;  ------&amp;gt; commit &amp;lt;-----&#xA;             |&#xA;             |&#xA;             V&#xA;           tree&#xA;             |&#xA;             |&#xA;             V&#xA;           blob&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can see from the above ascii graph that the &amp;lsquo;commit&amp;rsquo; object itself points to a &amp;lsquo;tree&amp;rsquo; object, and that tree object points to a &amp;lsquo;blob&amp;rsquo; object.  We&amp;rsquo;ll dig into these reference &amp;lsquo;object&amp;rsquo; types in more detail in the &amp;ldquo;&lt;a href=&#34;#object-types&#34;&gt;Object Types&lt;/a&gt;&amp;rdquo; section.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth clarifying now that although we conceptually talk in terms of &amp;lsquo;branches&amp;rsquo; in git, the internal directory structure (where references to branches are stored) uses the term &amp;lsquo;heads&amp;rsquo; instead. It&amp;rsquo;s a terrible name (like most things in git&amp;rsquo;s lexicon), but it&amp;rsquo;s best to just accept it and move on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason git uses &amp;lsquo;references&amp;rsquo; is it enables users to be able to refer to a specific commit without having to remember the full SHA1 hash.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine wanting to checkout your master branch but instead of just executing &lt;code&gt;git checkout master&lt;/code&gt; you had to remember the specific hash.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Not very practical heh.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;the-head-reference&#34;&gt;The HEAD reference&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you recall from earlier, we said the &lt;code&gt;HEAD&lt;/code&gt; file contains a pointer to the tip of the &lt;em&gt;current&lt;/em&gt; branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we were to look at the &lt;code&gt;.git/HEAD&lt;/code&gt; file we would find that by default it has the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ref: refs/heads/master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see it&amp;rsquo;s a pointer to another location (the reference &lt;code&gt;.git/refs/heads/master&lt;/code&gt;), which means it&amp;rsquo;s a pointer to a pointer!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that &lt;code&gt;refs/heads/master&lt;/code&gt; is a reference file (which refers to our master branch), and the contents of that file is a pointer to a commit hash. So this is telling us that ultimately &lt;code&gt;HEAD&lt;/code&gt; is pointing to our &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But at this point in time I&amp;rsquo;ve only executed &lt;code&gt;git init&lt;/code&gt;, and so I&amp;rsquo;ve not actually &lt;em&gt;committed&lt;/em&gt; anything into git. This means that there isn&amp;rsquo;t actually a &lt;code&gt;master&lt;/code&gt; file inside of the &lt;code&gt;.git/refs/heads&lt;/code&gt; subdirectory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look back at the earlier directory tree (which we printed after running &lt;code&gt;git init&lt;/code&gt;), we&amp;rsquo;ll notice that although there is a &lt;code&gt;.git/refs/heads&lt;/code&gt; directory, there is no &lt;code&gt;master&lt;/code&gt; file. A file called &lt;code&gt;master&lt;/code&gt; won&amp;rsquo;t exist in that subdirectory &lt;em&gt;until&lt;/em&gt; I make my first commit.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you recall from earlier I said that the &lt;code&gt;refs/heads&lt;/code&gt; subdirectory was essentially a synonym for &amp;lsquo;branches&amp;rsquo; created locally for this project. Hence, the default file referenced by the &lt;code&gt;HEAD&lt;/code&gt; file is &lt;code&gt;master&lt;/code&gt; (because it&amp;rsquo;s referencing the &lt;code&gt;master&lt;/code&gt; branch).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now create a commit so that we can see a &lt;code&gt;refs/heads/master&lt;/code&gt; file and what it points to&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ echo foo &amp;gt; foo.txt&#xA;$ git add foo.txt&#xA;$ git commit -m &amp;quot;foo&amp;quot;&#xA;&#xA;[master (root-commit) b5d34b6] foo&#xA; 1 file changed, 1 insertion(+)&#xA; create mode 100644 foo.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we do this we&amp;rsquo;ll find git has created a &lt;code&gt;master&lt;/code&gt; file inside of &lt;code&gt;.git/refs/heads&lt;/code&gt; and the contents of that file is the hash of my first commit (which indicates that the &lt;code&gt;master&lt;/code&gt; reference file, or &amp;lsquo;branch&amp;rsquo;, is pointing at a specific commit snapshot):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When you execute a command (such as) &lt;code&gt;git checkout master&lt;/code&gt;, internally git will resolve &lt;code&gt;master&lt;/code&gt; into &lt;code&gt;refs/heads/master&lt;/code&gt; and that is what tells git which commit object to now point to.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;subcommands-and-references&#34;&gt;Subcommands and References&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Although a reference is a pointer to a commit hash, it doesn&amp;rsquo;t mean you can use a reference within a git subcommand.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example subcommand that works fine with a reference: &lt;code&gt;git log&lt;/code&gt;. We can use &lt;code&gt;git log origin/master&lt;/code&gt;, and git will know to internally resolve that reference to the fully qualified path &lt;code&gt;.git/refs/remotes/origin/master&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Knowing that, we would also know that it is possible to use a partial reference path such as &lt;code&gt;git log refs/remotes/origin/master&lt;/code&gt; or maybe &lt;code&gt;git log remotes/origin/master&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All these variations work fine, but we typically use &lt;code&gt;git log origin/master&lt;/code&gt; for convenience (because it&amp;rsquo;s less typing).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But using a shorted &amp;lsquo;reference&amp;rsquo; isn&amp;rsquo;t possible with commands like &lt;code&gt;git checkout&lt;/code&gt; and &lt;code&gt;git pull&lt;/code&gt; for different reasons. With &lt;code&gt;git pull&lt;/code&gt; if we look at &lt;code&gt;man git-pull&lt;/code&gt; we see we need to provide a &lt;code&gt;&amp;lt;repository&amp;gt; &amp;lt;refspec&amp;gt;&lt;/code&gt; and that means the refspec we provide will be scoped to &lt;code&gt;.git/refs/remote/&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I look at &lt;code&gt;.git/refs/remote/&lt;/code&gt; I&amp;rsquo;ll see only a single directory &lt;code&gt;origin&lt;/code&gt;, and inside of that are all the branches (i.e. refspecs) for the &lt;code&gt;origin&lt;/code&gt; remote. So if I attempted to do something like &lt;code&gt;git pull origin HEAD&lt;/code&gt; this wouldn&amp;rsquo;t work because there&amp;rsquo;s a &lt;code&gt;HEAD&lt;/code&gt; file inside of that &lt;code&gt;origin&lt;/code&gt; directory (and it points to a different commit from our local &lt;code&gt;HEAD&lt;/code&gt; in &lt;code&gt;.git/HEAD&lt;/code&gt;)!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means we&amp;rsquo;d end up trying to pull the changes from the remote &lt;code&gt;master&lt;/code&gt;!! Which happens because &lt;code&gt;HEAD&lt;/code&gt; on the remote is setup to track the &lt;code&gt;master&lt;/code&gt; branch&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git remote show origin&#xA;&#xA;* remote origin&#xA;  Fetch URL: git@github.com:example/repo.git&#xA;  Push  URL: git@github.com:example/repo.git&#xA;  HEAD branch: master&#xA;  Remote branches:&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So subsequently doing &lt;code&gt;git pull origin HEAD&lt;/code&gt; would bring in &lt;em&gt;lots&lt;/em&gt; of unexpected changes to your local branch 😬&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;using &lt;code&gt;HEAD&lt;/code&gt; isn&amp;rsquo;t a problem when doing something like &lt;code&gt;git push origin HEAD&lt;/code&gt; because it&amp;rsquo;s a fundamentally different operation and so git knows to reference the local &lt;code&gt;HEAD&lt;/code&gt; file to get the commit range before &lt;em&gt;pushing&lt;/em&gt; to the remote.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Similarly, using a shortened &amp;lsquo;reference&amp;rsquo; isn&amp;rsquo;t possible with a command like &lt;code&gt;git checkout&lt;/code&gt; as its internal logic will cause a &lt;code&gt;detached HEAD&lt;/code&gt; state (e.g. if you were to do something like &lt;code&gt;git checkout refs/heads/master&lt;/code&gt; instead of &lt;code&gt;git checkout master&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now understand what a &amp;lsquo;detacted HEAD&amp;rsquo; means, and why it is a &lt;code&gt;git checkout&lt;/code&gt; would cause that when using a refspec&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;detached-head&#34;&gt;Detached HEAD&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Internally git does recognize the reference and can resolve it to the appropriate &lt;code&gt;.git/refs&lt;/code&gt; directory, but the &lt;em&gt;behaviour&lt;/em&gt; of the checkout command changes when checking out a reference that is a qualified path such as &lt;code&gt;refs/heads/master&lt;/code&gt;. What you would discover is you don&amp;rsquo;t checkout the branch but are placed into a &amp;lsquo;detached HEAD&amp;rsquo; at the relevant commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why is that? Well, if we look at the documentation for the checkout subcommand (&lt;code&gt;man git-checkout&lt;/code&gt;) we would discover&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;if it (the given branch name) refers to a branch (i.e., a name that, when prepended with &amp;ldquo;refs/heads/&amp;rdquo;, is a valid ref), then that branch is checked out. Otherwise, if it refers to a valid commit, your HEAD becomes &amp;ldquo;detached&amp;rdquo; and you are no longer on any branch.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Running &lt;code&gt;git checkout master&lt;/code&gt; means you&amp;rsquo;ve given an identifier (i.e. &lt;code&gt;master&lt;/code&gt;) that git can internally resolve to &lt;code&gt;refs/heads/master&lt;/code&gt; and thus git will happily checkout that branch, while &lt;code&gt;git checkout refs/heads/master&lt;/code&gt; is a &lt;em&gt;direct&lt;/em&gt; reference that git first resolves to a commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hence it&amp;rsquo;s like you had actually run the subcommand &lt;code&gt;git checkout &amp;lt;commit-hash&amp;gt;&lt;/code&gt;, and so git puts you into a detached HEAD state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re unfamiliar with what a &amp;lsquo;detached HEAD&amp;rsquo; state is, then it simply means the &lt;code&gt;HEAD&lt;/code&gt; file no longer is pointing at a reference such as &lt;code&gt;.git/refs/heads/master&lt;/code&gt; but &lt;em&gt;directly&lt;/em&gt; to a commit hash. The purpose of a detached HEAD is to allow you to do work &lt;em&gt;off&lt;/em&gt; a branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve never had a need to work &amp;lsquo;off&amp;rsquo; a branch (&lt;code&gt;:shrugs:&lt;/code&gt;) and so I can only presume there are situations where you would want to do that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, now that we have our first commit let&amp;rsquo;s dig a little deeping into the &amp;lsquo;objects&amp;rsquo; git defines, and how the &lt;code&gt;.git&lt;/code&gt; directory structure has changed&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;object-types&#34;&gt;Object Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are four main types of objects in git:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;commit&lt;/li&gt;&#xA;&lt;li&gt;tree&lt;/li&gt;&#xA;&lt;li&gt;blob&lt;/li&gt;&#xA;&lt;li&gt;tag&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we&amp;rsquo;ll primarily be covering the first three object types.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Since we committed a single file into git there has been a few new files and directories created:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;index&lt;/code&gt;: a binary file containing a sorted list of path names.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;COMMIT_EDITMSG&lt;/code&gt;: temporary file used to store latest commit message.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99&lt;/code&gt;: the &lt;code&gt;foo.txt&lt;/code&gt; file (type: blob)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;objects/b5/d34b608ce697f0d20d011ee569529bca3feee8&lt;/code&gt;: commit message data (type: commit)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;objects/fc/f0be4d7e45f0ef9592682ad68e42270b0366b4&lt;/code&gt;: directory tree (type: tree)&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that the new objects are stored in a subdirectory which uses the first two characters from the hash of the object&amp;rsquo;s contents.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, the &lt;code&gt;foo.txt&lt;/code&gt; blob object&amp;rsquo;s content was hashed into &lt;code&gt;257cc5642cb1a054f08cc83f2d943e56fd3ebe99&lt;/code&gt;. Next git took the first two characters &lt;code&gt;25&lt;/code&gt; and made a subdirectory, and then moved the object into that directory while naming the object file using the remaining characters (i.e. &lt;code&gt;7cc5642cb1a054f08cc83f2d943e56fd3ebe99&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to look at these files you&amp;rsquo;ll need a couple different plumbing commands: &lt;code&gt;git ls-files&lt;/code&gt; and &lt;code&gt;git cat-files&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the &lt;code&gt;index&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;index&lt;/code&gt; is a binary file which tracks our working directory and our staging area (use &lt;code&gt;--stage&lt;/code&gt; flag to see staging area). The index enables fast comparisons between the tree object it defines and the working tree.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll need to use &lt;code&gt;git ls-files&lt;/code&gt; in order to read the contents:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git ls-files&#xA;&#xA;foo.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It only has &lt;code&gt;foo.txt&lt;/code&gt; tracked, which is correct. There are no other files or directories at this point in time (we&amp;rsquo;ll add more as we go).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To look at the different &amp;lsquo;objects&amp;rsquo; we&amp;rsquo;ll use the &lt;code&gt;git cat-files&lt;/code&gt; command which decompresses the file and displays the file contents (we&amp;rsquo;ll use the &lt;code&gt;-t&lt;/code&gt; flag to return the &amp;lsquo;type&amp;rsquo; and the &lt;code&gt;-p&lt;/code&gt; flag to &amp;lsquo;print&amp;rsquo; the contents).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we don&amp;rsquo;t provide the path (e.g. &lt;code&gt;objects/../...&lt;/code&gt;) as the argument, but the sha itself (shortened sha is acceptable too).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git cat-file -t 257cc5642cb1a054f08cc83f2d943e56fd3ebe99&#xA;blob&#xA;&#xA;$ git cat-file -p 257cc5642cb1a054f08cc83f2d943e56fd3ebe99&#xA;foo&#xA;&#xA;$ git cat-file -t b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;commit&#xA;&#xA;$ git cat-file -p b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;tree fcf0be4d7e45f0ef9592682ad68e42270b0366b4&#xA;author Integralist &amp;lt;example@gmail.com&amp;gt; 1585480397 +0100&#xA;committer Integralist &amp;lt;example@gmail.com&amp;gt; 1585480397 +0100&#xA;&#xA;foo&#xA;&#xA;$ git cat-file -t fcf0be4d7e45f0ef9592682ad68e42270b0366b4&#xA;tree&#xA;&#xA;$ git cat-file -p fcf0be4d7e45f0ef9592682ad68e42270b0366b4&#xA;100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99    foo.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s also interesting is that when you execute command such as &lt;code&gt;git add&lt;/code&gt;, git will &amp;lsquo;conceptually&amp;rsquo; copy the file to your staging area, but internally it has created a &amp;lsquo;blob&amp;rsquo; object. While a command such as &lt;code&gt;git commit&lt;/code&gt; then creates the &amp;lsquo;commit&amp;rsquo; and &amp;lsquo;tree&amp;rsquo; objects to reference the already existing &amp;lsquo;blob&amp;rsquo; object. I mention this because I wanted to be clear that these three objects don&amp;rsquo;t all get created at the same time.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;snapshots-not-differences&#34;&gt;Snapshots, Not Differences&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We saw earlier an ascii graph that indicated the hierarchy of these objects. It showed that git reference types (e.g. remotes, branches and tags) all point to a &amp;lsquo;commit&amp;rsquo; object. This commit object will include a pointer to a &amp;lsquo;tree&amp;rsquo; object, and the tree object is a list of files (i.e. blobs) and directories (i.e. more trees).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s this graph that builds up the entire snapshot of the repository. This is why you shouldn&amp;rsquo;t think of a git commit as being a patch or set of changes to a bunch of files, but instead should see each commit as a complete snapshot of your entire project at a singular point in time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If any files or directories change, then their commit hash will change and thus the HEAD commit will consist of different &lt;code&gt;tree&lt;/code&gt; and &lt;code&gt;blob&lt;/code&gt; objects (resulting in a different hash-tree graph).&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind, let&amp;rsquo;s start by looking at the commit object we have (&lt;code&gt;git cat-file -p b5d34b6&lt;/code&gt;). We can see the first line says &lt;code&gt;tree&lt;/code&gt; followed by a hash (all other information is the typical commit information you&amp;rsquo;re used to seeing when you run &lt;code&gt;git status&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at the tree object &lt;code&gt;git cat-file -p fcf0be4&lt;/code&gt; (which the commit object linked to), then we can see it consists of a single line: a blob object with its hash and its filename &lt;code&gt;foo.txt&lt;/code&gt; (this makes sense as our project only contains this single file).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, let&amp;rsquo;s look at the blob object &lt;code&gt;git cat-file -p 257cc56&lt;/code&gt; (which the tree object linked to), then we can see the contents of that blob object is the contents of the &lt;code&gt;foo.txt&lt;/code&gt; file itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, so what happens if I add a new file &lt;code&gt;bar.txt&lt;/code&gt; and a new subdirectory &lt;code&gt;baz&lt;/code&gt; with another file &lt;code&gt;qux.txt&lt;/code&gt; within that subdirectory&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ tree&#xA;.&#xA;├── bar.txt&#xA;├── baz&#xA;│   └── qux.txt&#xA;└── foo.txt&#xA;&#xA;1 directory, 3 files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once I add &lt;code&gt;baz/qux.txt&lt;/code&gt; and commit it I then inspect the new objects in my &lt;code&gt;.git/objects&lt;/code&gt; folder. From there I locate the commit object (I do that by looking at the &lt;code&gt;.git/refs/heads/master&lt;/code&gt; and seeing what commit hash it has) and once I &lt;code&gt;cat-file -p&lt;/code&gt; that hash, I follow its &lt;code&gt;tree&lt;/code&gt; pointer&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git cat-file -p edc6771b338b472d901358e530db7cede202c1c7&#xA;&#xA;100644 blob 5716ca5987cbf97d6bb54920bea6adde242d87e6    bar.txt&#xA;040000 tree 3d15e426c95bac2548d7255af9c5e240df786e03    baz&#xA;100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99    foo.txt&#xA;&#xA;$ git cat-file -p 3d15e426c95bac2548d7255af9c5e240df786e03&#xA;&#xA;100644 blob 100b0dec8c53a40e4de7714b2c612dad5fad9985    qux.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the above output that the tree object not only includes my project files, but now a &lt;code&gt;baz&lt;/code&gt; directory (itself a tree object). Looking at that tree object shows there is one file inside of it (a blob object for &lt;code&gt;qux.txt&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we review the &lt;code&gt;index&lt;/code&gt; file again we&amp;rsquo;ll see our new set of files/directories:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git ls-files&#xA;&#xA;bar.txt&#xA;baz/qux.txt&#xA;foo.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;tags&#34;&gt;Tags&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Along the way I&amp;rsquo;ve been tagging my commits. A tag (as far as git internals are concerned) is another &amp;lsquo;object&amp;rsquo; type. Let&amp;rsquo;s look at my tags:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git tag -n&#xA;&#xA;v1  foo&#xA;v2  an anotated tag&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see I have two separate tags, and each one points at a different commit (the v1 tag was a lightweight tag and so the associated &lt;code&gt;foo&lt;/code&gt; comes from the commit message, while the v2 tag was an annotated tag and so the message I gave at that point was displayed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to see the commit that a tag is associated with, we&amp;rsquo;ll need another plumbing subcommand &lt;code&gt;rev-list&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git rev-list -n 1 v1&#xA;&#xA;b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;&#xA;$ git rev-list -n 1 v2&#xA;&#xA;0b56156eba23ae9bee8c32137605397cf7c9e88e&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But for us to see what the &amp;lsquo;tag&amp;rsquo; object type looks like internally, we need to get the hash that the tag reference file is set to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ cat .git/refs/tags/v1&#xA;&#xA;b5d34b608ce697f0d20d011ee569529bca3feee8&#xA;&#xA;$ cat .git/refs/tags/v2&#xA;&#xA;75d37b7c37173def7a0a8cd43d674edc8e9ce614&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we have that hash we can use &lt;code&gt;cat-file&lt;/code&gt; to see the &amp;lsquo;tag&amp;rsquo; object:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git cat-file -t 75d37b7c37173def7a0a8cd43d674edc8e9ce614&#xA;&#xA;tag&#xA;&#xA;$ git cat-file -p 75d37b7c37173def7a0a8cd43d674edc8e9ce614&#xA;&#xA;object 0b56156eba23ae9bee8c32137605397cf7c9e88e&#xA;type commit&#xA;tag v2&#xA;tagger Integralist &amp;lt;example@gmail.com&amp;gt; 1585592962 +0100&#xA;&#xA;an anotated tag&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so you may have noticed I used &lt;code&gt;cat-file&lt;/code&gt; on the v2 (annotated) tag, but not on the v1 (lightweight) tag. That was not an accidental omission.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A lightweight tag is just a reference to a commit hash, but an annotated tag is more complex and so a &amp;lsquo;tag object&amp;rsquo; is created, and we can see that when we inspect the hash inside the v2 tag reference.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see the tag object includes a pointer to the &amp;lsquo;commit&amp;rsquo; object (&lt;code&gt;0b56156eba23ae9bee8c32137605397cf7c9e88e&lt;/code&gt;) as well as information about the &amp;lsquo;tagger&amp;rsquo; (in this case &lt;em&gt;me&lt;/em&gt;!)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;remotes&#34;&gt;Remotes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you add a remote like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git remote add origin git@github.com:Integralist/dotfiles.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can now look at the configuration of our remote:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ git remote show origin&#xA;&#xA;* remote origin&#xA;  Fetch URL: git@github.com:Integralist/dotfiles.git&#xA;  Push  URL: git@github.com:Integralist/dotfiles.git&#xA;  HEAD branch: master&#xA;  Remote branches:&#xA;    linux                                new (next fetch will store in remotes/origin)&#xA;    master                               new (next fetch will store in remotes/origin)&#xA;    minimal-mac-version-of-linux-version new (next fetch will store in remotes/origin)&#xA;  Local ref configured for &#39;git push&#39;:&#xA;    master pushes to master (local out of date)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You might be confused though if you were to look at &lt;code&gt;.git/refs&lt;/code&gt; and don&amp;rsquo;t see a &lt;code&gt;remotes&lt;/code&gt; subdirectory. This happens automatically if you &lt;em&gt;clone&lt;/em&gt; an existing repository, but it&amp;rsquo;ll also be created when executing &lt;code&gt;git fetch&lt;/code&gt; after manually adding a new remote to an &lt;em&gt;existing&lt;/em&gt; repository.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I added my new &lt;code&gt;origin&lt;/code&gt; remote (see above), but it was only once I had executed a &lt;code&gt;git fetch&lt;/code&gt; was I then able to see a &amp;lsquo;remote&amp;rsquo; reference:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;refs/&#xA;| remotes/&#xA;| | origin/&#xA;| | | master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If I inspect the &lt;code&gt;.git/refs/remotes/origin/master&lt;/code&gt; file, then I&amp;rsquo;ll see the latest commit my remote &lt;code&gt;master&lt;/code&gt; branch is on. It&amp;rsquo;s also interesting to remember what we mentioned earlier about references that point to commits being interchangeable with commit hashes in various subcommands.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;code&gt;git diff&lt;/code&gt; allows you to specify two branches to compare against each other (remember a branch is just a reference file that points to a commit hash), and so you might want to compare your local &lt;code&gt;master&lt;/code&gt; against your remote &lt;code&gt;master&lt;/code&gt; branch:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff master..origin/master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is just a shortened way of doing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff master..refs/remotes/origin/master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which itself is just a shortened way of doing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff master..c3865b72b019ced930cfc601b09b874685c29e72&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;one last thing I wanted to mention (and there was no other place really to mention this) is that git comes with a UI! you can execute the command &lt;code&gt;gitk&lt;/code&gt; to use it.&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/git-internals/</guid>
      <link>https://www.integralist.co.uk/posts/git-internals/</link>
      <pubDate>Sun, 29 Mar 2020 00:00:00 +0000</pubDate>
      <title>Git Internals</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In this post I wanted to discuss a relatively simple, but important topic: Context Managers. I want to cover the what, the why and the how.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Content Managers abstract away &amp;lsquo;clean-up&amp;rsquo; logic.&lt;/li&gt;&#xA;&lt;li&gt;Define a class with &lt;code&gt;__enter__&lt;/code&gt;/&lt;code&gt;__exit__&lt;/code&gt; methods.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;__enter__&lt;/code&gt; method is similar to a &lt;code&gt;try&lt;/code&gt; block.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;__exit__&lt;/code&gt; method is similar to a &lt;code&gt;finally&lt;/code&gt; block.&lt;/li&gt;&#xA;&lt;li&gt;Reduce boilerplate with &lt;a href=&#34;https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;@contextlib.contextmanager&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-context-manager&#34;&gt;What is a Context Manager?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Officially&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the &lt;code&gt;with&lt;/code&gt; statement, but can also be used by directly invoking their methods. &amp;ndash; &lt;a href=&#34;https://docs.python.org/3/reference/datamodel.html#context-managers&#34; target=&#34;_blank&#34;&gt;Python Docs&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In simpler terms it means: a Context Manager can ensure code that requires &amp;lsquo;clean-up&amp;rsquo; logic to be executed, is done so in a more idiomatic/Pythonic way.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-use-a-context-manager&#34;&gt;Why use a Context Manager?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The classic example given is when opening lots of file in Python:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;files = []&#xA;&#xA;for _ in range(100000):&#xA;    f = open(&#39;foo.txt&#39;, &#39;w&#39;)&#xA;    files.append(f)&#xA;    f.close()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice each file object&amp;rsquo;s &lt;code&gt;.close()&lt;/code&gt; method is called to ensure the file descriptor is released. If we &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; do that, then your Operating System would exhaust its allowed limit of open file descriptors.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To make this code more Pythonic and cleaner, we can utilize Context Managers.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-to-use-a-context-manager&#34;&gt;How to use a Context Manager?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are two ways to utilize a Context Manager&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;with&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@contextlib.contextmanager&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;with&#34;&gt;&lt;code&gt;with&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We can use the &lt;code&gt;with&lt;/code&gt; statement to define a similar block of code to our earlier &amp;lsquo;open multiple files&amp;rsquo; example.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;with&lt;/code&gt; statement expects a &amp;lsquo;Context Manager&amp;rsquo; to be provided, and there are already a few built-in Python objects designed as Context Managers; such as the &lt;code&gt;open&lt;/code&gt; function we saw used in our above example code.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;another example is &lt;a href=&#34;https://docs.python.org/3/library/threading.html#threading.Lock&#34; target=&#34;_blank&#34;&gt;threading.Lock&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is what the code might look like when using &lt;code&gt;with&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;files = []&#xA;&#xA;for _ in range(100000):&#xA;    with open(&#39;foo.txt&#39;, &#39;w&#39;) as f:&#xA;        files.append(f)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how we didn&amp;rsquo;t have to explicitly call &lt;code&gt;.close()&lt;/code&gt; on each file object generated by &lt;code&gt;open&lt;/code&gt;. That&amp;rsquo;s because &lt;code&gt;open&lt;/code&gt; works as a Context Manager and knows how to clean-up after itself when called via the &lt;code&gt;with&lt;/code&gt; statement.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll show you how to implement your own Context Manager in the following section: &lt;a href=&#34;#how-to-implement-a-context-manager&#34;&gt;How to implement a Context Manager?&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;contextlib-contextmanager&#34;&gt;&lt;code&gt;@contextlib.contextmanager&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Python provides a decorator function &lt;code&gt;@contextlib.contextmanager&lt;/code&gt; which is actually a callable class (i.e. it defines &lt;code&gt;__call__&lt;/code&gt; magic method) that enables custom context managers (e.g. your own code you want to act as a context manager) to use simpler code than the traditional &amp;lsquo;class-based&amp;rsquo; implementation we previously mentioned.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means if you have custom objects that need to implement clean-up logic (similar to how &lt;code&gt;open&lt;/code&gt; does), then you can decorate your own function so it &lt;em&gt;behaves&lt;/em&gt; like a Context Manager, while your function itself simply uses a &lt;code&gt;yield&lt;/code&gt; statement, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from contextlib import contextmanager&#xA;&#xA;files = []&#xA;&#xA;@contextmanager&#xA;def open_file(path, mode): &#xA;    file = open(path, mode)&#xA;    yield file&#xA;    file.close()&#xA;&#xA;for _ in range(100000):&#xA;    with open_file(&#39;foo.txt&#39;, &#39;w&#39;) as f:&#xA;        files.append(f)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example code we&amp;rsquo;ve effectively recreated the &lt;code&gt;open&lt;/code&gt; Context Manager just to demonstrate the principle.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-to-implement-a-context-manager&#34;&gt;How to implement a Context Manager?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;ve already seen how to implement a Context Manager using the &lt;code&gt;@contextlib.contextmanager&lt;/code&gt; decorator (see previous sub-section), but how do we implement a class-based version of a Context Manager?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That requires us to define a class which implements &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt; methods. Below is an example, again replicating the &lt;code&gt;open&lt;/code&gt; function to keep things simple:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;files = []&#xA;&#xA;class Open():&#xA;    def __init__(self, filename, mode):&#xA;        self.filename = filename&#xA;        self.mode = mode&#xA;&#xA;    def __enter__(self):&#xA;        self.open_file = open(self.filename, self.mode)&#xA;        return self.open_file&#xA;&#xA;    def __exit__(self, *args):&#xA;        self.open_file.close()&#xA;&#xA;for _ in range(100000):&#xA;    with Open(&#39;foo.txt&#39;, &#39;w&#39;) as f:&#xA;        files.append(f)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for more information, see &lt;a href=&#34;https://docs.python.org/3/library/stdtypes.html#typecontextmanager&#34; target=&#34;_blank&#34;&gt;Context Manager Types&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;when-to-use-one-or-the-other&#34;&gt;When to use one or the other?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One thing I noticed recently was that the &lt;code&gt;contextmanager&lt;/code&gt; variation wouldn&amp;rsquo;t execute an &amp;lsquo;exit&amp;rsquo; if an exception was raised during execution of the code, while the more verbose &amp;lsquo;class-based&amp;rsquo; implementation &lt;em&gt;would&lt;/em&gt;. See the following code for an example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from contextlib import contextmanager&#xA;&#xA;@contextmanager&#xA;def foo():&#xA;    print(&amp;quot;enter!&amp;quot;)&#xA;    yield &amp;quot;foobar&amp;quot;&#xA;    print(&amp;quot;exit!&amp;quot;)&#xA;&#xA;try:&#xA;    with foo() as f:&#xA;        raise Exception(&amp;quot;unexpected&amp;quot;)&#xA;        print(f&amp;quot;f was: {f}&amp;quot;)&#xA;except Exception as e:&#xA;    print(f&amp;quot;whoops: {e}&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output is not what I expected:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;enter!&#xA;whoops: unexpected&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how there is no &lt;code&gt;exit!&lt;/code&gt; printed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now compare this to a &amp;lsquo;class-based&amp;rsquo; example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo():&#xA;    def __enter__(self):&#xA;        print(&amp;quot;enter!&amp;quot;)&#xA;&#xA;    def __exit__(self, *args):&#xA;        print(&amp;quot;exit!&amp;quot;, args)&#xA;&#xA;try:&#xA;    with Foo() as f:&#xA;        raise Exception(&amp;quot;unexpected&amp;quot;)&#xA;        print(f&amp;quot;f was: {f}&amp;quot;)&#xA;except Exception as e:&#xA;    print(f&amp;quot;whoops: {e}&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output is as expected:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;enter!&#xA;exit! (&amp;lt;class &#39;Exception&#39;&amp;gt;, Exception(&#39;unexpected&#39;), &amp;lt;traceback object at 0x108882d00&amp;gt;)&#xA;whoops: unexpected&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;i.e. we see &lt;em&gt;both&lt;/em&gt; an enter and exit message.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can get the &lt;code&gt;contextmanager&lt;/code&gt; to behave as we might have expected it to (e.g. the same as the &amp;lsquo;class-based&amp;rsquo; implementation) by ensuring the function that calls &lt;code&gt;yield&lt;/code&gt; is wrapped in a &lt;code&gt;try/finally&lt;/code&gt; block, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from contextlib import contextmanager&#xA;&#xA;@contextmanager&#xA;def foo():&#xA;    print(&amp;quot;enter!&amp;quot;)&#xA;    try:&#xA;        yield &amp;quot;foobar&amp;quot;&#xA;    finally:&#xA;        print(&amp;quot;exit!&amp;quot;)&#xA;&#xA;try:&#xA;    with foo() as f:&#xA;        raise Exception(&amp;quot;unexpected&amp;quot;)&#xA;        print(f&amp;quot;f was: {f}&amp;quot;)&#xA;except Exception as e:&#xA;    print(f&amp;quot;whoops: {e}&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of this is now what we might expect&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;enter!&#xA;exit!&#xA;whoops: unexpected&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When choosing between the two options &lt;code&gt;contextmanager&lt;/code&gt; and &amp;lsquo;class-based&amp;rsquo; implementation, it might be worth keeping this caveat in mind.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;multiple-context-managers-in-a-single-with-statement&#34;&gt;Multiple Context Managers in a single With statement&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One interesting aspect of the &lt;code&gt;with&lt;/code&gt; statement is that you can execute multiple context managers as part of its block control. Meaning when the &lt;code&gt;with&lt;/code&gt; block completes, then all context managers will be cleaned up.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from contextlib import contextmanager&#xA;&#xA;@contextmanager&#xA;def foo():&#xA;    print(&amp;quot;enter!&amp;quot;)&#xA;    try:&#xA;        yield &amp;quot;foobar&amp;quot;&#xA;    finally:&#xA;        print(&amp;quot;exit!&amp;quot;)&#xA;&#xA;&#xA;with foo() as f1, foo() as f2, foo() as f3:&#xA;    print(f&amp;quot;f1 was: {f1}&amp;quot;)&#xA;    print(f&amp;quot;f2 was: {f2}&amp;quot;)&#xA;    print(f&amp;quot;f3 was: {f3}&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively you can utilize &lt;code&gt;contextlib.ExitStack&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from contextlib import contextmanager, ExitStack&#xA;&#xA;@contextmanager&#xA;def foo():&#xA;    print(&amp;quot;enter!&amp;quot;)&#xA;    try:&#xA;        yield &amp;quot;foobar&amp;quot;&#xA;    finally:&#xA;        print(&amp;quot;exit!&amp;quot;)&#xA;&#xA;with ExitStack() as stack:&#xA;    managers = [stack.enter_context(foo()) for cm in range(3)]&#xA;    print(managers)  # [&#39;foobar&#39;, &#39;foobar&#39;, &#39;foobar&#39;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-context-managers/</guid>
      <link>https://www.integralist.co.uk/posts/python-context-managers/</link>
      <pubDate>Mon, 06 Jan 2020 00:00:00 +0000</pubDate>
      <title>Python 101: Context Managers</title>
    </item>
    <item>
      <description>&lt;p&gt;In this post I&amp;rsquo;m going to be talking about what a generator is and how it compares to a coroutine, but to understand these two concepts (generators and coroutines) we&amp;rsquo;ll need to take a step back and understand the underlying concept of an Iterator.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each section leads onto the next, so it&amp;rsquo;s best to read this post in the order the sections are defined. Unless you&amp;rsquo;re already familiar with earlier segments and prefer to jump ahead.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The summary of everything we&amp;rsquo;ll be discussing below is this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Iterators let you iterate over your own custom object.&lt;/li&gt;&#xA;&lt;li&gt;Generators are built upon Iterators (they reduce boilerplate).&lt;/li&gt;&#xA;&lt;li&gt;Generator Expressions are even more concise Generators †&lt;/li&gt;&#xA;&lt;li&gt;Coroutines &lt;em&gt;are&lt;/em&gt; Generators, but their &lt;code&gt;yield&lt;/code&gt; accepts values.&lt;/li&gt;&#xA;&lt;li&gt;Coroutines can pause and resume execution (great for concurrency).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† think &lt;a href=&#34;https://gist.github.com/e5310d1082b0ff8307e39b71a6f9bae5&#34; target=&#34;_blank&#34;&gt;comprehensions&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;iterators&#34;&gt;Iterators&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;According to the official &lt;a href=&#34;https://docs.python.org/3.7/glossary.html#term-iterator&#34; target=&#34;_blank&#34;&gt;Python glossary&lt;/a&gt;, an &amp;lsquo;iterator&amp;rsquo; is&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;An object representing a stream of data.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;why-use-iterators&#34;&gt;Why use Iterators?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An interator is useful because it enables any custom object to be iterated over using the standard Python &lt;code&gt;for-in&lt;/code&gt; syntax. This is ultimately how the internal list and dictionary types work, and how they allow &lt;code&gt;for-in&lt;/code&gt; to iterate over them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;More importantly, an iterator (as we&amp;rsquo;ll discover) is very memory efficient and means there is only ever one element being handled at once. Thus you could have an iterator object that provides an infinite sequence of elements and you&amp;rsquo;ll never find your program exhausting its memory allocation.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;iterator-implementation&#34;&gt;Iterator Implementation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An iterator is (typically) an object that implements both the &lt;code&gt;__iter__&lt;/code&gt; and &lt;code&gt;__next__&lt;/code&gt; &amp;lsquo;dunder&amp;rsquo; methods, although the &lt;code&gt;__next__&lt;/code&gt; method doesn&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; to be defined as part of the same object as where &lt;code&gt;__iter__&lt;/code&gt; is defined. Let me clarify&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An &amp;lsquo;iterator&amp;rsquo; is really just a container of some data. This &amp;lsquo;container&amp;rsquo; must have an &lt;code&gt;__iter__&lt;/code&gt; method which, according to the &lt;a href=&#34;https://docs.python.org/3.7/library/stdtypes.html#iterator.__iter__&#34; target=&#34;_blank&#34;&gt;protocol documentation&lt;/a&gt;, should return an iterator object (i.e. something that has the &lt;code&gt;__next__&lt;/code&gt; method). It&amp;rsquo;s the &lt;code&gt;__next__&lt;/code&gt; method that moves forward through the relevant collection of data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So you could design a single class that contains both the &lt;code&gt;__iter__&lt;/code&gt; and &lt;code&gt;__next__&lt;/code&gt; methods (like I demonstrate below), or you might want to have the &lt;code&gt;__next__&lt;/code&gt; method defined as part of a separate class (it&amp;rsquo;s up to you and whatever you feel works best for your project).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the Python docs for &lt;a href=&#34;https://docs.python.org/3.7/library/collections.abc.html#collections.abc.Iterator&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;collections.abc&lt;/code&gt;&lt;/a&gt; highlight the other &amp;lsquo;protocols&amp;rsquo; that Python has and the various methods they require (see an &lt;a href=&#34;/posts/design-python/#interfaces-protocols-and-abstract-methods&#34;&gt;earlier post of mine&lt;/a&gt; that discusses protocols + abstract classes in detail). If you&amp;rsquo;re unfamiliar with &amp;lsquo;dunder&amp;rsquo; methods, then I&amp;rsquo;ll refer you to an excellent post: &lt;a href=&#34;https://rszalski.github.io/magicmethods/&#34; target=&#34;_blank&#34;&gt;a guide to magic methods&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;By implementing these two methods it enables Python to iterate over a &amp;lsquo;collection&amp;rsquo;. It doesn&amp;rsquo;t matter what the collection is, as long as the iterator object defines the behaviour that lets Python know how to iterate over it.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;iterator-example&#34;&gt;Iterator Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Below is a contrived example that shows how to create such an object. In this example we pass in a list of strings to a class constructor and the class implements the relevant methods that allow &lt;code&gt;for-in&lt;/code&gt; to iterate over that collection of data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo:&#xA;    def __init__(self, collection):&#xA;        self.collection = collection&#xA;        self.index = 0&#xA;&#xA;    def __iter__(self):&#xA;        &amp;quot;&amp;quot;&amp;quot;&#xA;        we return self so the &#39;iterator object&#39; &#xA;        is the Foo class instance itself,&#xA;        &#xA;        but we could have returned a new instance &#xA;        of a completely different class, so long as&#xA;        that other class had __next__ defined on it.&#xA;        &amp;quot;&amp;quot;&amp;quot;&#xA;        return self&#xA;&#xA;    def __next__(self):&#xA;        &amp;quot;&amp;quot;&amp;quot;&#xA;        this method is handling state and informing&#xA;        the container of the iterator where we are&#xA;        currently pointing to within our data collection.&#xA;        &amp;quot;&amp;quot;&amp;quot;&#xA;        if self.index &amp;gt; len(self.collection)-1:&#xA;            raise StopIteration&#xA;&#xA;        value = self.collection[self.index]&#xA;        self.index += 1&#xA;&#xA;        return value&#xA;&#xA;# we are now able to loop over our custom Foo class!&#xA;for element in Foo([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]):&#xA;    print(element)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;raising the &lt;code&gt;StopIteration&lt;/code&gt; exception is a requirement for implementing an iterator correctly.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;With this example implementation, we can also iterate over our &lt;code&gt;Foo&lt;/code&gt; class &lt;em&gt;manually&lt;/em&gt;, using the &lt;code&gt;iter&lt;/code&gt; and &lt;code&gt;next&lt;/code&gt; functions, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo = Foo([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;])&#xA;iterator = iter(foo)&#xA;&#xA;next(iterator)  # &#39;a&#39;&#xA;next(iterator)  # &#39;b&#39;&#xA;next(iterator)  # &#39;c&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;iter(foo)&lt;/code&gt; is the same as &lt;code&gt;foo.__iter__()&lt;/code&gt;, while &lt;code&gt;next(iterator)&lt;/code&gt; is the same as &lt;code&gt;iterator.__next__()&lt;/code&gt; &amp;ndash; so these functions are basic syntactic sugar provided by the standard library that helps make our code look nicer.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This type of iterator is referred to as a &amp;lsquo;class-based iterator&amp;rsquo; and isn&amp;rsquo;t the only way to implement an &lt;em&gt;iterable&lt;/em&gt; object. &lt;a href=&#34;#generators&#34;&gt;Generators&lt;/a&gt; and &lt;a href=&#34;#generator-expressions&#34;&gt;Generator Expressions&lt;/a&gt; (see the following sections) are other ways of iterating over an object in a memory efficient way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can also &lt;em&gt;realize&lt;/em&gt; the full collection by using the &lt;code&gt;list&lt;/code&gt; function, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;iterator = Foo([&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;])&#xA;list(iterator)  # [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be careful doing this, because if the iterator is yielding an unbounded number of elements, then this will exhaust your application&amp;rsquo;s memory!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;generators&#34;&gt;Generators&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;According to the official &lt;a href=&#34;https://docs.python.org/3.7/library/stdtypes.html#generator-types&#34; target=&#34;_blank&#34;&gt;Python documentation&lt;/a&gt;, a &amp;lsquo;generator&amp;rsquo; provides&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A convenient way to implement the iterator protocol. If a container object&amp;rsquo;s &lt;code&gt;__iter__()&lt;/code&gt; method is implemented as a generator, it will automatically return an iterator object.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;why-use-generators&#34;&gt;Why use Generators?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;They offer nice syntax sugar around creating a simple Iterator, but also help reduce the boilerplate code necessary to make something iterable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A Generator can help reduce the code boilerplate associated with a &amp;lsquo;class-based&amp;rsquo; iterator because they&amp;rsquo;re designed to handle the &amp;lsquo;state management&amp;rsquo; logic you would otherwise have to write yourself.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generator-implementation&#34;&gt;Generator Implementation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A Generator is a function that returns a &amp;lsquo;generator iterator&amp;rsquo;, so it acts similar to how &lt;code&gt;__iter__&lt;/code&gt; works (remember it returns an iterator).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In fact a Generator is a subclass of an Iterator. The generator function itself should utilize a &lt;code&gt;yield&lt;/code&gt; statement to return control back to the caller of the generator function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The caller can then advance the generator iterator by using either the &lt;code&gt;for-in&lt;/code&gt; statement or &lt;code&gt;next&lt;/code&gt; function (as we saw earlier with the &amp;lsquo;class-based&amp;rsquo; Iterator examples), which again highlights how generators are indeed a subclass of an Iterator.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a generator &amp;lsquo;yields&amp;rsquo; it actually pauses the function at that point in time and returns a value. Calling &lt;code&gt;next&lt;/code&gt; (or as part of a &lt;code&gt;for-in&lt;/code&gt;) will move the function forward, where it will either complete the generator function or stop at the next &lt;code&gt;yield&lt;/code&gt; declaration within the generator function.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generator-example&#34;&gt;Generator Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example prints &lt;code&gt;a&lt;/code&gt;, then &lt;code&gt;b&lt;/code&gt;, finally &lt;code&gt;c&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def generator():&#xA;  yield &amp;quot;a&amp;quot;&#xA;  yield &amp;quot;b&amp;quot;&#xA;  yield &amp;quot;c&amp;quot;&#xA;&#xA;for v in generator():&#xA;     print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we used the &lt;code&gt;next()&lt;/code&gt; function instead then we would do something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gen = generator()&#xA;next(gen)  # a&#xA;next(gen)  # b&#xA;next(gen)  # c&#xA;next(gen)  # raises StopIteration&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that this has greatly reduced our code boilerplate compared to the custom &amp;lsquo;class-based&amp;rsquo; Iterator we created earlier, as there is no need to define the &lt;code&gt;__iter__&lt;/code&gt; nor &lt;code&gt;__next__&lt;/code&gt; methods on a class instance (nor manage any state ourselves). We simple call &lt;code&gt;yield&lt;/code&gt;!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If our use case is simple enough, then Generators are the way to go. Otherwise we might need a custom &amp;lsquo;class-based&amp;rsquo; Iterator if we have very specific logic we need to execute.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember, Iterators (and by extension Generators) are very memory efficient and thus we could have a generator that yields an unbounded number of elements like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def unbounded_generator():&#xA;    while True:&#xA;        yield &amp;quot;some value&amp;quot;&#xA;&#xA;gen = unbounded_generator()&#xA;&#xA;next(gen)  # some value&#xA;next(gen)  # some value&#xA;next(gen)  # some value&#xA;next(gen)  # some value&#xA;next(gen)  # ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So, as mentioned earlier, be careful when using &lt;code&gt;list()&lt;/code&gt; over a generator function (see below example), as that will realize the entire collection and could exhaust your application memory.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def generator():&#xA;  yield &amp;quot;a&amp;quot;&#xA;  yield &amp;quot;b&amp;quot;&#xA;  yield &amp;quot;c&amp;quot;&#xA;&#xA;gen = generator()&#xA;list(gen)  # [a, b, c]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;generator-expressions&#34;&gt;Generator Expressions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;According to the official &lt;a href=&#34;https://www.python.org/dev/peps/pep-0289/&#34; target=&#34;_blank&#34;&gt;PEP 289 document&lt;/a&gt; for generator expressions&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Generator expressions are a high-performance, memory–efficient generalization of list comprehensions and generators.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In essence they are a way of creating a generator using a syntax very similar to &lt;a href=&#34;https://gist.github.com/e5310d1082b0ff8307e39b71a6f9bae5&#34; target=&#34;_blank&#34;&gt;list comprehensions&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of a generator function that will print &lt;code&gt;&amp;quot;foo&amp;quot;&lt;/code&gt; five times:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def generator(limit):&#xA;    for i in range(limit):&#xA;        yield &amp;quot;foo&amp;quot;&#xA;&#xA;for v in generator(5):&#xA;    print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now here is is the same thing as a generator expression:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;for v in (&amp;quot;foo&amp;quot; for i in range(5)):&#xA;    print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The syntax for a generator expression is also very similar to those used by comprehensions, except that instead of the boundary/delimeter characters being &lt;code&gt;[]&lt;/code&gt; or &lt;code&gt;{}&lt;/code&gt;, we use &lt;code&gt;()&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(expression for item in collection if condition)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;so although not demonstrated, you can also &amp;lsquo;filter&amp;rsquo; yielded values due to the support for &amp;ldquo;if&amp;rdquo; conditions.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;nested-generators-i-e-yield-from&#34;&gt;Nested Generators (i.e. &lt;code&gt;yield from&lt;/code&gt;)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Python 3.3 provided the &lt;code&gt;yield from&lt;/code&gt; statement, which offered some basic syntactic sugar around dealing with nested generators.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see an example of what we would have to do if we didn&amp;rsquo;t have &lt;code&gt;yield from&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def baz():&#xA;    for i in range(10):&#xA;        yield i&#xA;&#xA;def bar():&#xA;    for i in range(5):&#xA;        yield i&#xA;&#xA;def foo():&#xA;    for v in bar():&#xA;        yield v&#xA;    for v in baz():&#xA;        yield v&#xA;&#xA;for v in foo():&#xA;    print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how (inside the &lt;code&gt;foo&lt;/code&gt; generator function) we have two separate &lt;code&gt;for-in&lt;/code&gt; loops, one for each nested generator.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now look at what this becomes when using &lt;code&gt;yield from&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def baz():&#xA;    for i in range(10):&#xA;        yield i&#xA;&#xA;def bar():&#xA;    for i in range(5):&#xA;        yield i&#xA;&#xA;def foo():&#xA;    yield from bar()&#xA;    yield from baz()&#xA;&#xA;for v in foo():&#xA;    print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK so not exactly a ground breaking feature, but if you were ever confused by &lt;code&gt;yield from&lt;/code&gt; you now know that it&amp;rsquo;s a simple facade over the &lt;code&gt;for-in&lt;/code&gt; syntax.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although it&amp;rsquo;s worth pointing out that if we didn&amp;rsquo;t have &lt;code&gt;yield from&lt;/code&gt; we still could have reworked our original code using the &lt;code&gt;itertool&lt;/code&gt; module&amp;rsquo;s &lt;code&gt;chain()&lt;/code&gt; function, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from itertools import chain&#xA;&#xA;def baz():&#xA;    for i in range(10):&#xA;        yield i&#xA;&#xA;def bar():&#xA;    for i in range(5):&#xA;        yield i&#xA;&#xA;def foo():&#xA;    for v in chain(bar(), baz()):&#xA;        yield v&#xA;&#xA;for v in foo():&#xA;    print(v)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;refer to &lt;a href=&#34;https://www.python.org/dev/peps/pep-0380/&#34; target=&#34;_blank&#34;&gt;PEP 380&lt;/a&gt; for more details on &lt;code&gt;yield from&lt;/code&gt; and the rationale for its inclusion in the Python language.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;coroutines&#34;&gt;Coroutines&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Coroutines (as far as Python is concerned) have historically been designed to be an extension to &lt;a href=&#34;#generators&#34;&gt;Generators&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed. &amp;ndash; &lt;a href=&#34;https://en.wikipedia.org/wiki/Coroutine&#34; target=&#34;_blank&#34;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;why-use-coroutines&#34;&gt;Why use Coroutines?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Because coroutines can pause and resume execution context, they&amp;rsquo;re well suited to conconcurrent processing, as they enable the program to determine when to &amp;lsquo;context switch&amp;rsquo; from one point of the code to another.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why coroutines are commonly used when dealing with concepts such as an &lt;a href=&#34;/posts/python-asyncio/#event-loop&#34;&gt;event loop&lt;/a&gt; (which Python&amp;rsquo;s &lt;code&gt;asyncio&lt;/code&gt; is built upon).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;coroutines-implementation&#34;&gt;Coroutines Implementation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Generators use the &lt;code&gt;yield&lt;/code&gt; keyword to return a value at some point in time within a function, but with coroutines the &lt;code&gt;yield&lt;/code&gt; directive can &lt;em&gt;also&lt;/em&gt; be used on the right-hand side of an &lt;code&gt;=&lt;/code&gt; operator to signify it will &lt;em&gt;accept a value&lt;/em&gt; at that point in time.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;coroutines-example&#34;&gt;Coroutines Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Below is an example of a coroutine. Remember! a coroutine is still a generator and so you&amp;rsquo;ll see our example uses features that are related to generators (such as &lt;code&gt;yield&lt;/code&gt; and the &lt;code&gt;next()&lt;/code&gt; function):&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;refer to the code comments for extra clarity.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def foo():&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    notice we use yield in both the &#xA;    traditional generator sense and&#xA;    also in the coroutine sense.&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    msg = yield  # coroutine feature&#xA;    yield msg    # generator feature&#xA;&#xA;coro = foo()&#xA;&#xA;# because a coroutine is a generator&#xA;# we need to advance the returned generator&#xA;# to the first yield within the generator function&#xA;next(coro)&#xA;&#xA;# the .send() syntax is specific to a coroutine&#xA;# this sends &amp;quot;bar&amp;quot; to the first yield &#xA;# so the msg variable will be assigned that value&#xA;result = coro.send(&amp;quot;bar&amp;quot;)&#xA;&#xA;# because our coroutine also yields the msg variable&#xA;# it means we can print that value&#xA;print(result)  # bar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;coro&lt;/code&gt; is an identifier commonly used to refer to a coroutine. For more information on other available coroutine methods, please refer to the &lt;a href=&#34;https://docs.python.org/3.8/reference/datamodel.html#coroutines&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Below is an example of a coroutine using &lt;code&gt;yield&lt;/code&gt; to return a value to the caller prior to the value &lt;em&gt;received&lt;/em&gt; via a caller using the &lt;code&gt;.send()&lt;/code&gt; method:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def foo():&#xA;    msg = yield &amp;quot;beep&amp;quot;&#xA;    yield msg&#xA;&#xA;coro = foo()&#xA;&#xA;print(next(coro))  # beep&#xA;&#xA;result = coro.send(&amp;quot;bar&amp;quot;)&#xA;&#xA;print(result)  # bar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see in the above example that when we moved the generator coroutine to the first &lt;code&gt;yield&lt;/code&gt; statement (using &lt;code&gt;next(coro)&lt;/code&gt;), that the value &lt;code&gt;&amp;quot;beep&amp;quot;&lt;/code&gt; was returned for us to &lt;code&gt;print&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;asyncio-generator-based-coroutines&#34;&gt;Asyncio: generator based coroutines&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When the &lt;code&gt;asyncio&lt;/code&gt; module was first released it didn&amp;rsquo;t support the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax, so when it was introduced, to ensure any legacy code that had a function that needed to be run concurrently (i.e. awaited) would have to use an &lt;code&gt;asyncio.coroutine&lt;/code&gt; decorator function to allow it to be compatible with the new &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;refer to &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-task.html#generator-based-coroutines&#34; target=&#34;_blank&#34;&gt;the documentation&lt;/a&gt; for information on this deprecated (as of Python 3.10) feature, as well as some other functions like &lt;code&gt;asyncio.iscoroutine&lt;/code&gt; that are specific to generator based coroutines.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The original generator based coroutines meant any &lt;code&gt;asyncio&lt;/code&gt; based code would have used &lt;code&gt;yield from&lt;/code&gt; to await on &lt;a href=&#34;/posts/python-asyncio/#futures&#34;&gt;Futures&lt;/a&gt; and other coroutines.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how to use both the new &lt;code&gt;async&lt;/code&gt; coroutines with legacy generator based coroutines:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@asyncio.coroutine&#xA;def old_style_coroutine():&#xA;    yield from asyncio.sleep(1)&#xA;&#xA;async def main():&#xA;    await old_style_coroutine()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;asyncio-new-async-coroutines&#34;&gt;Asyncio: new async coroutines&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Coroutines created with &lt;code&gt;async def&lt;/code&gt; are implemented using the more recent &lt;code&gt;__await__&lt;/code&gt; dunder method (see &lt;a href=&#34;https://docs.python.org/3.8/reference/datamodel.html#coroutines&#34; target=&#34;_blank&#34;&gt;documentation here&lt;/a&gt;), while generator based coroutines are using a legacy &amp;lsquo;generator&amp;rsquo; based implementation.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;types-of-coroutines&#34;&gt;Types of Coroutines&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This has led to the term &amp;lsquo;coroutine&amp;rsquo; meaning multiple things in different contexts. We now have:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;simple coroutines&lt;/strong&gt;: traditional generator coroutine (no async io).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;generator coroutines&lt;/strong&gt;: async io using legacy &lt;code&gt;asyncio&lt;/code&gt; implementation.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;native coroutines&lt;/strong&gt;: async io using latest &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; implementation.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are a couple of interesting decorator functions provided by Python that can be a bit confusing, due to these functions appearing to have overlapping functionality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They don&amp;rsquo;t overlap, but do appear to be used together:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;types.coroutine&lt;/code&gt;: converts generator function into a coroutine.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.coroutine&lt;/code&gt;: abstraction ensuring &lt;code&gt;asyncio&lt;/code&gt; compatibility.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as we&amp;rsquo;ll see in a moment, &lt;code&gt;asyncio.coroutine&lt;/code&gt; actually calls &lt;code&gt;types.coroutine&lt;/code&gt;. You should ideally use the former when dealing with &lt;code&gt;asyncio&lt;/code&gt; code.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;More specifically, if we look at the implementation of the &lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/asyncio/coroutines.py#L105&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;asyncio.coroutine&lt;/code&gt; code&lt;/a&gt; we can see:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;If decorated function is already a coroutine, then just return it.&lt;/li&gt;&#xA;&lt;li&gt;If decorated function is a generator, then convert it to a coroutine (using &lt;code&gt;types.coroutine&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Otherwise wrap the decorated function such that when it&amp;rsquo;s converted to a coroutine it&amp;rsquo;ll await any resulting awaitable value.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s interesting about &lt;code&gt;types.coroutine&lt;/code&gt; is that if your decorated function were to remove any reference to a &lt;code&gt;yield&lt;/code&gt;, then the function will be executed immediately rather than returning a generator. See &lt;a href=&#34;https://stackoverflow.com/a/49477233&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt; Stack Overflow answer for more information as to where that behaviour was noticed.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-generators/</guid>
      <link>https://www.integralist.co.uk/posts/python-generators/</link>
      <pubDate>Sat, 28 Dec 2019 00:00:00 +0000</pubDate>
      <title>Python 101: iterators, generators, coroutines</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I was confused by the Python tool &lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;tox&lt;/a&gt; for a long time, and was unsure what it was really used for considering lots of different Python packages appeared to rely on tox&amp;rsquo;s configuration file (e.g. &lt;code&gt;tox.ini&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this post I&amp;rsquo;m going to briefly explain what the tox tool is, and what a &lt;code&gt;tox.ini&lt;/code&gt; configuration file looks like and why that configuration file can be used for more than just serving the purposes of the tox tool.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-tox&#34;&gt;What is tox?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Tox is a tool that creates &lt;a href=&#34;/posts/python-app-dependencies/#virtual-environments&#34;&gt;virtual environments&lt;/a&gt;, and installs the configured dependencies for those environments, for the purpose of testing a Python package (i.e. something that will be shared via &lt;a href=&#34;https://pypi.org/&#34; target=&#34;_blank&#34;&gt;PyPi&lt;/a&gt;, and so it only works with code that defines a &lt;code&gt;setup.py&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;PyPi == Python Package Index (i.e. where you &lt;em&gt;typically&lt;/em&gt; install all your Python packages from, when executing &lt;code&gt;pip install&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The file that you use to configure tox can be one of the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;tox.ini&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; (see &lt;a href=&#34;https://www.python.org/dev/peps/pep-0518/&#34; target=&#34;_blank&#34;&gt;PEP 518&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;setup.cfg&lt;/code&gt; (see &lt;a href=&#34;https://packaging.python.org/guides/distributing-packages-using-setuptools/&#34; target=&#34;_blank&#34;&gt;official guide to distributing packages&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;these ^^ are all &lt;a href=&#34;https://en.wikipedia.org/wiki/INI_file&#34; target=&#34;_blank&#34;&gt;ini file&lt;/a&gt; formats &amp;ndash; which is information that will become more relevant/important later on.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;example-tox-ini&#34;&gt;Example tox.ini&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;All configuration options for tox can be found here: &lt;a href=&#34;https://tox.readthedocs.io/en/latest/config.html&#34; target=&#34;_blank&#34;&gt;tox.readthedocs.io/en/latest/config.html&lt;/a&gt; but the below example is a simple demonstration of how you might configure tox for a real package (e.g. this is an &lt;em&gt;actual&lt;/em&gt; &lt;code&gt;tox.ini&lt;/code&gt; file I&amp;rsquo;ve used).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-ini&#34;&gt;[tox]&#xA;envlist = &#xA;    py37, lint&#xA;toxworkdir = &#xA;    {env:TOX_WORK_DIR}&#xA;&#xA;[testenv]&#xA;setenv =&#xA;    PYTHONDONTWRITEBYTECODE = 1&#xA;whitelist_externals =&#xA;    /bin/bash&#xA;deps = &#xA;    -rrequirements-dev.txt&#xA;commands =&#xA;    py.test --cov={envsitepackagesdir}/bf_tornado -m &amp;quot;not integration&amp;quot;&#xA;&#xA;[testenv:dev]&#xA;usedevelop=True&#xA;recreate = False&#xA;commands =&#xA;    # to run arbitrary commands: tox -e dev -- bash&#xA;    {posargs:py.test --cov=bf_tornado}&#xA;&#xA;[testenv:lint]&#xA;deps =&#xA;    flake8==3.8.3&#xA;    mypy==0.782&#xA;commands =&#xA;    flake8 bf_tornado&#xA;    mypy --verbose --ignore-missing-imports --package bf_tornado&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the name after &lt;code&gt;testenv:&lt;/code&gt; is the &lt;em&gt;name&lt;/em&gt; of the virtual environment that will be created (e.g. &lt;code&gt;testenv:foo&lt;/code&gt; will create a &amp;ldquo;foo&amp;rdquo; virtual environment).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;configuring-other-packages&#34;&gt;Configuring &lt;em&gt;other&lt;/em&gt; packages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &lt;code&gt;tox.ini&lt;/code&gt; file can be used to configure different types of packages, which is confusing at first because the tox home page suggests that tox is used to test &lt;em&gt;your own&lt;/em&gt; packages you plan on distributing to PyPi.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What the tox authors mean by that description, is that the &lt;code&gt;tox&lt;/code&gt; &lt;em&gt;command&lt;/em&gt; itself is used to handle testing your packages, while the &lt;code&gt;tox.ini&lt;/code&gt; &lt;em&gt;configuration file&lt;/em&gt; is just one such file that can be used to contain configuration information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why other packages, such as &lt;a href=&#34;https://flake8.pycqa.org/en/latest/index.html&#34; target=&#34;_blank&#34;&gt;Flake8&lt;/a&gt; allow you to &lt;a href=&#34;https://flake8.pycqa.org/en/latest/user/configuration.html&#34; target=&#34;_blank&#34;&gt;configure Flake8&lt;/a&gt; using the &lt;code&gt;tox.ini&lt;/code&gt; file, as well as alternatives such as: &lt;code&gt;setup.cfg&lt;/code&gt; or &lt;code&gt;.flake8&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The key to understanding why this works is as follows: each of these files conform to the &lt;a href=&#34;https://en.wikipedia.org/wiki/INI_file&#34; target=&#34;_blank&#34;&gt;ini file&lt;/a&gt; format. So you&amp;rsquo;re free to use whatever file &lt;em&gt;name&lt;/em&gt; you feel best suits your project, while the format of the file will stay consistent to what is expected of an &lt;code&gt;.ini&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-do-multiple-tools-support-tox-ini&#34;&gt;Why do multiple tools support &lt;code&gt;tox.ini&lt;/code&gt;?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The benefit of these various tools supporting the &lt;code&gt;tox.ini&lt;/code&gt; filename specifically is to help reduce the number of configuration files a project requires.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you needed a unique configuration file for every Python command line tool you use in your project. How many would that result in? How hard would it be to remember all the various file names?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind, below is an example that shows various Python packages being configured within a &lt;code&gt;tox.ini&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And in case it&amp;rsquo;s unclear, the configuration inside of the &lt;code&gt;tox.ini&lt;/code&gt; file is used instead of having to pass those configuration values via the command line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in the case of a tool such as &lt;code&gt;flake8&lt;/code&gt;, instead of using &lt;code&gt;flake8 --max-line-length=120&lt;/code&gt; you could just call &lt;code&gt;flake8&lt;/code&gt; and the flag value is extracted from the configuration file.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-ini&#34;&gt;[flake8]&#xA;max_line_length = 120&#xA;ignore = E261,E265,E402  # http://pep8.readthedocs.org/en/latest/intro.html#error-codes&#xA;&#xA;[coverage:run]&#xA;branch = True&#xA;&#xA;[coverage:report]&#xA;show_missing = True&#xA;exclude_lines =&#xA;    raise NotImplementedError&#xA;    return NotImplemented&#xA;    def __repr__&#xA;omit = bf_tornado/testing.py&#xA;&#xA;[pytest]&#xA;addopts = &#xA;    --strict -p no:cacheprovider --showlocals&#xA;markers =&#xA;    integration: mark a test as an integration test that makes http calls.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;bonus-section&#34;&gt;Bonus Section&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Although not directly related to the conversation about &lt;code&gt;tox.ini&lt;/code&gt; I thought it worth mentioning that I discovered recently the Python logging library allows you to be able to configure logging via an ini configuration file!&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reference: &lt;a href=&#34;https://docs.python.org/3/howto/logging.html#configuring-logging&#34; target=&#34;_blank&#34;&gt;docs.python.org/3/howto/logging.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The ini file might look something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[loggers]&#xA;keys=root,simpleExample&#xA;&#xA;[handlers]&#xA;keys=consoleHandler&#xA;&#xA;[formatters]&#xA;keys=simpleFormatter&#xA;&#xA;[logger_root]&#xA;level=DEBUG&#xA;handlers=consoleHandler&#xA;&#xA;[logger_simpleExample]&#xA;level=DEBUG&#xA;handlers=consoleHandler&#xA;qualname=simpleExample&#xA;propagate=0&#xA;&#xA;[handler_consoleHandler]&#xA;class=StreamHandler&#xA;level=DEBUG&#xA;formatter=simpleFormatter&#xA;args=(sys.stdout,)&#xA;&#xA;[formatter_simpleFormatter]&#xA;format=%(asctime)s - %(name)s - %(levelname)s - %(message)s&#xA;datefmt=&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The Python program that uses this file might look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import logging&#xA;import logging.config&#xA;&#xA;logging.config.fileConfig(&#39;logging.conf&#39;)&#xA;&#xA;# create logger&#xA;logger = logging.getLogger(&#39;simpleExample&#39;)&#xA;&#xA;# &#39;application&#39; code&#xA;logger.debug(&#39;debug message&#39;)&#xA;logger.info(&#39;info message&#39;)&#xA;logger.warning(&#39;warn message&#39;)&#xA;logger.error(&#39;error message&#39;)&#xA;logger.critical(&#39;critical message&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice though, the &lt;em&gt;name&lt;/em&gt; of the configuration file we imported was &lt;code&gt;logging.conf&lt;/code&gt; (no &lt;code&gt;.ini&lt;/code&gt; extension). It doesn&amp;rsquo;t matter that the file doesn&amp;rsquo;t use the &lt;code&gt;.ini&lt;/code&gt; extension as long as the format of the file itself conforms to the ini format.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/tox-ini/</guid>
      <link>https://www.integralist.co.uk/posts/tox-ini/</link>
      <pubDate>Wed, 18 Dec 2019 00:00:00 +0000</pubDate>
      <title>Understanding the purpose of tox.ini</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This blog post aims to demonstrate the most practical way to install multiple versions of Python, and of setting up &amp;lsquo;virtual environments&amp;rsquo; for macOS userso&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll also dig into how to manage our project dependencies (e.g. we&amp;rsquo;ll be discussing the classic Pip and &lt;code&gt;requirements.txt&lt;/code&gt; format) + our approach for avoiding newer tools such as &lt;a href=&#34;https://pypi.org/project/poetry/&#34; target=&#34;_blank&#34;&gt;Poetry&lt;/a&gt; and &lt;a href=&#34;https://pypi.org/project/pipenv/&#34; target=&#34;_blank&#34;&gt;Pipenv&lt;/a&gt;, which I feel are just too complicated/overkill for the majority of use cases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why is this not a simple thing to do? I hear you ask! Well, because we don&amp;rsquo;t live in a perfect world and sometimes the overhead of &amp;lsquo;convenience&amp;rsquo; can be worth the cost otherwise incurred, and sometimes it can&amp;rsquo;t.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll start by describing briefly what a virtual environment is, and then I&amp;rsquo;ll move onto the point of this article and the options we have available to us.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;virtual-environments&#34;&gt;Virtual Environments&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A cooperatively isolated runtime environment that allows Python users and applications to install and upgrade Python distribution packages without interfering with the behaviour of other Python applications running on the same system. &amp;ndash; &lt;a href=&#34;https://docs.python.org/3/glossary.html#term-virtual-environment&#34; target=&#34;_blank&#34;&gt;Python Glossary&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;To simplify: if you work on multiple Python projects and each project uses the same external dependency (e.g. the &lt;a href=&#34;https://requests.readthedocs.io/en/master/&#34; target=&#34;_blank&#34;&gt;Requests&lt;/a&gt; HTTP library), then it&amp;rsquo;s possible your application (for &lt;em&gt;each&lt;/em&gt; project) will be written to support a specific version of that dependency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Having a virtual environment setup for each project means you can have project specific Python package installs. For example, project &amp;lsquo;foo&amp;rsquo; can use the Request library version 1.0 while project &amp;lsquo;bar&amp;rsquo; can use version 2.0 (which might introduce a different API).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the official documentation on Virtual Environments can be found &lt;a href=&#34;https://docs.python.org/3/tutorial/venv.html&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;creating-virtual-environments&#34;&gt;Creating Virtual Environments&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you installed Python using Homebrew (e.g. &lt;code&gt;brew install python3&lt;/code&gt;) and you don&amp;rsquo;t care what version of Python you have, you only care about having virtual environments, then you can utilize the built-in &lt;code&gt;venv&lt;/code&gt; module like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python3 -m venv /foo/bar&#xA;source /foo/bar/bin/activate&#xA;python3 -m pip install &amp;lt;dependencies&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will ensure you only install third-party packages/modules into the specific virtual environment you&amp;rsquo;ve just activated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only downside of this very simple approach is that installing Python via Homebrew means you&amp;rsquo;ll have only a single version of Python installed and you have no control over what that version is, let alone have multiple versions installed (as the &lt;code&gt;python3&lt;/code&gt; command will be overwritten each time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This consideration is actually &lt;em&gt;critical&lt;/em&gt; to understand when you consider the Linux OS internals use the same Python version as exposed to the end user. Meaning if you mess up your Python install on Linux, then there is a high chance you&amp;rsquo;ll break the entire operating system!&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want to prevent accidentally executing &lt;code&gt;pip install&lt;/code&gt; outside of a virtual environment then use &lt;code&gt;export PIP_REQUIRE_VIRTUALENV=true&lt;/code&gt; (it can also be set in a &lt;a href=&#34;https://github.com/Integralist/dotfiles/blob/master/.pip/pip.conf&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;~/.pip/pip.conf&lt;/code&gt;&lt;/a&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you require virtual environments across &lt;em&gt;multiple&lt;/em&gt; Python versions, then read the following couple of sections&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;installing-python-versions&#34;&gt;Installing Python Versions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So there are in fact &lt;em&gt;two&lt;/em&gt; ways of installing Python versions, but it&amp;rsquo;s much less practical in reality and so i&amp;rsquo;m only going to demonstrate &lt;em&gt;one&lt;/em&gt; of them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The two ways are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Manual compilation&lt;/li&gt;&#xA;&lt;li&gt;External build tool&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As you can imagine, manually compiling Python would be the more flexible solution, but the harsh reality is that compiling Python requires very specific dependencies that can be hard to get right (and most often it goes wrong).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So instead we&amp;rsquo;ll focus on the latter: an external tool called &lt;code&gt;pyenv&lt;/code&gt; which internally uses another external tool called &lt;code&gt;python-build&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;pyenv&lt;/code&gt;: let&amp;rsquo;s us switch Python versions easily&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;python-build&lt;/code&gt; let&amp;rsquo;s us install Python versions easily.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t need to install &lt;code&gt;python-build&lt;/code&gt; directly as it&amp;rsquo;ll be installed when you install &lt;code&gt;pyenv&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To install &lt;code&gt;pyenv&lt;/code&gt; execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install pyenv&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;yes, this means you need to be using &lt;a href=&#34;https://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt;, but let&amp;rsquo;s face it, it&amp;rsquo;s the defacto standard for macOS package management.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once installed you&amp;rsquo;ll be able to use the following commands:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;python-build --definitions&lt;/code&gt;: list all versions of Python available to be installed&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pyenv install &amp;lt;version&amp;gt;&lt;/code&gt;: install the version of Python you need&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Once you have installed the version of Python you need, now you just need to remember to &amp;lsquo;activate&amp;rsquo; it whenever you&amp;rsquo;re working on your project that requires that specific version of Python. To do that, you&amp;rsquo;ll need to do two things (and you only need to do them once):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;add &lt;code&gt;eval &amp;quot;$(pyenv init -)&amp;quot;&lt;/code&gt; to your &lt;code&gt;.bashrc&lt;/code&gt; (or shell of choice)&lt;/li&gt;&#xA;&lt;li&gt;execute &lt;code&gt;pyenv local &amp;lt;version&amp;gt;&lt;/code&gt; in your project directory&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;What the first point does is it&amp;rsquo;ll allow your shell to respond to any &lt;code&gt;.python-version&lt;/code&gt; file found within a directory on your computer. This file will contain a Python version.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What generates the &lt;code&gt;.python-version&lt;/code&gt; file is the latter point.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;virtual-environments-for-multiple-pythons&#34;&gt;Virtual Environments for multiple Pythons&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To setup virtual environments with Python is actually very simple (as we saw in the earlier part of this post), but not compatible when using an external build tool such as &lt;code&gt;pyenv&lt;/code&gt; because of where &lt;code&gt;pyenv&lt;/code&gt; installs Python binaries and how it switches between versions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But luckily there is an extension to &lt;code&gt;pyenv&lt;/code&gt; called &lt;code&gt;pyenv-virtualenv&lt;/code&gt; which can be installed like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install pyenv-virtualenv&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once installed, setting up a new virtual environment is as simple as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pyenv virtualenv foobar&#xA;pyenv activate foobar&#xA;pyenv deactivate foobar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want you can specify the Python version to create the virtual environment for: &lt;code&gt;pyenv virtualenv &amp;lt;version&amp;gt; &amp;lt;name&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;shell-configuration&#34;&gt;Shell Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is just a quick summary of the configuration lines added to my &lt;code&gt;.bashrc&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;eval &amp;quot;$(python3 -m pip completion --bash)&amp;quot;&#xA;eval &amp;quot;$(pyenv init -)&amp;quot;&#xA;eval &amp;quot;$(pyenv virtualenv-init -)&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;managing-dependencies&#34;&gt;Managing Dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When it comes to dealing with specific dependency versions, I like to use the method &lt;a href=&#34;https://www.kennethreitz.org/essays/a-better-pip-workflow&#34; target=&#34;_blank&#34;&gt;Kenneth Reitz&lt;/a&gt; published back in 2016.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this method keeps with the traditional &lt;code&gt;requirements.txt&lt;/code&gt; file as utilized by &lt;a href=&#34;https://pip.pypa.io/en/stable/&#34; target=&#34;_blank&#34;&gt;Pip&lt;/a&gt;. I mention this as you&amp;rsquo;ll notice with other tools (such as Pipenv or Poetry), that they move away from this established format and that can be a bit disruptive in terms of how Python teams have traditionally worked. I&amp;rsquo;m not saying it&amp;rsquo;s a bad thing, but change isn&amp;rsquo;t always good.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;problem-summary&#34;&gt;Problem Summary&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here is a summary of the problem we&amp;rsquo;re trying to solve:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;requirements.txt&lt;/code&gt; file typically doesn&amp;rsquo;t include the sub-dependencies required by your top-level dependencies (because that would require you to manually identify them and to type them all out, something that should be an automated process and so in practice never happens manually).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. you specify a top-level dependency of &lt;code&gt;foo&lt;/code&gt; (which might install version 1.0), but that internally requires the use of other third-party packages such as &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt; (and specific versions for each of them).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But a &lt;code&gt;pip install&lt;/code&gt; from a file that only includes the top-level dependencies could (over time) result in different sub-dependency versions being installed by either different members of your team or via your deployment platform.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. if you don&amp;rsquo;t specify a version for &lt;code&gt;foo&lt;/code&gt;, then in a months time when someone else (or your deployment platform) runs &lt;code&gt;pip install&lt;/code&gt; it will attempt to install the latest version of &lt;code&gt;foo&lt;/code&gt; which might be version 2.0 (and subsequently the third-party packages it uses might also change).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid that people have come to use &lt;code&gt;pip freeze&lt;/code&gt; after doing a &lt;code&gt;pip install&lt;/code&gt; to overwrite their &lt;code&gt;requirements.txt&lt;/code&gt; with a list of &lt;em&gt;all&lt;/em&gt; dependencies and their explicit versions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This solves the issue of installing from &lt;code&gt;requirements.txt&lt;/code&gt; in a months time when lots of your top-level dependencies release new breaking versions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem now is that you have to manually search for the top-level dependencies (in this new larger/more-indepth &lt;code&gt;requirements.txt&lt;/code&gt; file) and update them manually. Doing this might break things as you now don&amp;rsquo;t know what the sub-dependency versions should be set to.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;solution&#34;&gt;Solution&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So the approach we take with any project is to define a &lt;code&gt;requirements-to-freeze.txt&lt;/code&gt; file. This file will contain all your project&amp;rsquo;s top-level dependencies (inc. any &lt;em&gt;explicit&lt;/em&gt; versions required), for example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;requests[security]&#xA;flask&#xA;gunicorn==19.4.5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next we can generate our actual &lt;code&gt;requirements.txt&lt;/code&gt; file based upon the contents of &lt;code&gt;requirements-to-freeze.txt&lt;/code&gt; using the &lt;code&gt;pip freeze&lt;/code&gt; command, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python -m pip install -r requirements-to-freeze.txt&#xA;python -m pip freeze &amp;gt; requirements.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which will result in a &lt;code&gt;requirements.txt&lt;/code&gt; file that looks something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cffi==1.5.2&#xA;cryptography==1.2.2&#xA;enum34==1.1.2&#xA;Flask==0.10.1&#xA;gunicorn==19.4.5&#xA;idna==2.0&#xA;ipaddress==1.0.16&#xA;itsdangerous==0.24&#xA;Jinja2==2.8&#xA;MarkupSafe==0.23&#xA;ndg-httpsclient==0.4.0&#xA;pyasn1==0.1.9&#xA;pycparser==2.14&#xA;pyOpenSSL==0.15.1&#xA;requests==2.9.1&#xA;six==1.10.0&#xA;Werkzeug==0.11.4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This means you&amp;rsquo;ll never manually update &lt;code&gt;requirements.txt&lt;/code&gt; again. Any time you need to update a dependency you&amp;rsquo;ll do it in &lt;code&gt;requirements-to-freeze.txt&lt;/code&gt;, then re-run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python -m pip install -r requirements-to-freeze.txt&#xA;python -m pip freeze &amp;gt; requirements.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or instead of manually updating the dependencies in &lt;code&gt;requirements-to-freeze.txt&lt;/code&gt; you could use the &lt;code&gt;--upgrade&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python -m pip install -r requirements-to-freeze.txt --upgrade&#xA;python -m pip freeze &amp;gt; requirements.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make the process easier (see notes below for details) we can utilize a bash shell script (and docker) to help us:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#!/bin/bash&#xA;&#xA;# A quick and easy way to exhaustively freeze a set of &amp;quot;top level&amp;quot; Python&#xA;# dependencies for services following the &amp;quot;Better Pip Workflow&amp;quot; approach:&#xA;#&#xA;#     https://www.kennethreitz.org/essays/a-better-pip-workflow&#xA;#&#xA;# This script makes it easy to generate the frozen requirements without needing&#xA;# to juggle fresh virtualenvs or compile-time dependencies by instead&#xA;# installing the requirements in an ephemeral docker container.&#xA;#&#xA;# Example usage:&#xA;#&#xA;#     .freeze-requirements path/to/requirements-to-freeze.txt &amp;gt; path/to/requirements.txt&#xA;#&#xA;# To install extra base OS packages (e.g. mysql-dev), specify them in PACKAGES on the command line:&#xA;#&#xA;#     PACKAGES=&amp;quot;mysql-dev&amp;quot; ./freeze-requirements ...&#xA;&#xA;set -e&#xA;set -u&#xA;set -o pipefail&#xA;&#xA;DEFAULT_PYTHON_VERSION=3.8&#xA;PYTHON_VERSION=&amp;quot;${PYTHON_VERSION:-$DEFAULT_PYTHON_VERSION}&amp;quot;&#xA;&#xA;DEFAULT_PACKAGES=&amp;quot;gcc python-dev libssl-dev&amp;quot;&#xA;PACKAGES=&amp;quot;${DEFAULT_PACKAGES} ${PACKAGES:-}&amp;quot;&#xA;&#xA;TAG=&amp;quot;freeze-requirements-${PYTHON_VERSION}&amp;quot;&#xA;&#xA;requirements_file=&amp;quot;${1:-}&amp;quot;&#xA;&#xA;if [ &amp;quot;$requirements_file&amp;quot; == &amp;quot;&amp;quot; ]; then&#xA;    echo &amp;quot;Usage: $(basename $0) REQUIREMENTS_FILE&amp;quot; &amp;gt;&amp;amp;2&#xA;    exit 1&#xA;fi&#xA;&#xA;if [ ! -f &amp;quot;$requirements_file&amp;quot; ] &amp;amp;&amp;amp; [ &amp;quot;$requirements_file&amp;quot; != &amp;quot;-&amp;quot; ]; then&#xA;    echo &amp;quot;File not found: $requirements_file&amp;quot; &amp;gt;&amp;amp;2&#xA;    exit 1&#xA;fi&#xA;&#xA;docker build -t $TAG - &amp;gt;&amp;amp;2 &amp;lt;&amp;lt;EOF&#xA;FROM python:${PYTHON_VERSION}-slim&#xA;&#xA;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y ${PACKAGES}&#xA;RUN pip install virtualenv &amp;amp;&amp;amp; virtualenv /venv&#xA;EOF&#xA;&#xA;cat $requirements_file | exec docker run --rm -i -a stdin -a stdout -a stderr $TAG sh -c &#39;&#xA;cat &amp;gt;/tmp/requirements-to-freeze.txt&#xA;/venv/bin/pip install -r /tmp/requirements-to-freeze.txt &amp;gt;&amp;amp;2&#xA;/venv/bin/pip freeze -r /tmp/requirements-to-freeze.txt&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;caching-dependencies&#34;&gt;Caching Dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Starting with pip version 6.0 you can prevent having to reinstall dependencies that are used across multiple virtual environments by caching them (this is especially useful with Continuous Integration builds).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do so, add the following to your &lt;code&gt;~/.bashrc&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;export PIP_DOWNLOAD_CACHE=$HOME/.pip/cache&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively add it to your &lt;code&gt;~/.pip/pip.conf&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[global]&#xA;require-virtualenv = true&#xA;download-cache = $HOME/.pip/cache&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;command-line-packages&#34;&gt;Command Line Packages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As a bonus section I&amp;rsquo;m going to quickly mention the tool &lt;a href=&#34;https://github.com/pipxproject/pipx&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;pipx&lt;/code&gt;&lt;/a&gt; which allows us to install Python command line tools such that they are isolated binaries and so they don&amp;rsquo;t clutter up our top-level Python runtime space.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To install &lt;code&gt;pipx&lt;/code&gt;, the official instructions state you can install it via either Homebrew or via an existing Python interpreter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Homebrew install is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install pipx&#xA;pipx ensurepath&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Using an existing Python interpreter:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python3 -m pip install --user pipx&#xA;python3 -m pipx ensurepath&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But I found it didn&amp;rsquo;t work unless I omitted the &lt;code&gt;--user&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python3 -m pip install pipx&#xA;python3 -m pipx ensurepath&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;After that you can add the following to your &lt;code&gt;~/.bashrc&lt;/code&gt; (or similar for whatever shell you use):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pipx completions&#xA;# eval &amp;quot;$(register-python-argcomplete pipx)&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you&amp;rsquo;re able to safely install command line Python tools, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pipx install pycowsay&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you use the &lt;code&gt;PIP_REQUIRE_VIRTUALENV&lt;/code&gt; setting (mentioned earlier in this post) but you also installed &lt;code&gt;pipx&lt;/code&gt; via Homebrew, then you&amp;rsquo;ll find that doing so can cause problems because pipx can&amp;rsquo;t use its internal list function (as no virtual environment is currently activated). So to fix the issue always set the environment variable to false: &lt;code&gt;PIP_REQUIRE_VIRTUALENV=false pipx list&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-app-dependencies/</guid>
      <link>https://www.integralist.co.uk/posts/python-app-dependencies/</link>
      <pubDate>Sun, 01 Dec 2019 00:00:00 +0000</pubDate>
      <title>Python Management and Project Dependencies</title>
    </item>
    <item>
      <description>&lt;p&gt;This is a &lt;em&gt;quick&lt;/em&gt; guide to Python&amp;rsquo;s &lt;code&gt;asyncio&lt;/code&gt; module and is based on Python&#xA;version 3.8.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s start by addressing the elephant in the room: there are &lt;em&gt;many&lt;/em&gt; modules&#xA;provided by the Python standard library for handling&#xA;asynchronous/concurrent/multiprocess code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/_thread.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;_thread&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/threading.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;threading&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/multiprocessing.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;multiprocessing&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/asyncio.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;asyncio&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/concurrent.futures.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;concurrent.futures&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In this post we&amp;rsquo;re going to focus on the last two. Primarily we will be focusing&#xA;on &lt;code&gt;asyncio&lt;/code&gt;, before wrapping up with a look at some useful features of&#xA;&lt;code&gt;concurrent.futures&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The motivation for this post is to understand why you will most likely want to&#xA;use &lt;code&gt;asyncio&lt;/code&gt; over the other available modules (e.g. &lt;code&gt;_thread&lt;/code&gt; and &lt;code&gt;threading&lt;/code&gt;)&#xA;and when it&amp;rsquo;s actually more appropriate to use either &lt;code&gt;multiprocessing&lt;/code&gt; or&#xA;&lt;code&gt;concurrent.futures&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-focus-on-asyncio&#34;&gt;Why focus on asyncio?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One of the issues with writing concurrent code (using either the &lt;code&gt;_thread&lt;/code&gt; or&#xA;&lt;code&gt;threading&lt;/code&gt; modules) is that you suffer the cost of &amp;lsquo;CPU context switching&amp;rsquo; (as&#xA;a CPU core can only run one thread at a time) which although quick, isn&amp;rsquo;t free.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Multi-threaded code also has to deal with issues such as &amp;lsquo;race conditions&amp;rsquo;,&#xA;&amp;lsquo;dead/live locks&amp;rsquo; and &amp;lsquo;resource starvation&amp;rsquo; (where some threads are over&#xA;utilized and others are under utilized).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Asyncio avoids these issues, so let&amp;rsquo;s see how&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;a-quick-asyncio-summary&#34;&gt;A quick &lt;code&gt;asyncio&lt;/code&gt; summary&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;asyncio is a library to write concurrent code using the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; syntax. &amp;ndash; &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio.html&#34; target=&#34;_blank&#34;&gt;docs.python.org/3.8/library/asyncio.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The asyncio module provides both high-level and low-level APIs. Library and&#xA;Framework developers will be expected to use the low-level APIs, while all other&#xA;users are encouraged to use the high-level APIs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It differs conceptually from the more traditional &lt;code&gt;threading&lt;/code&gt; or &lt;code&gt;multiprocess&lt;/code&gt;&#xA;approach to asynchronous code execution in that it utilizes something called an&#xA;&lt;a href=&#34;#event-loop&#34;&gt;event loop&lt;/a&gt; to handle the scheduling of asynchronous &amp;lsquo;tasks&amp;rsquo;&#xA;instead of using more traditional threads or subprocesses.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Importantly, asyncio is designed to solve I/O network performance, &lt;em&gt;not&lt;/em&gt; CPU&#xA;bound operations (which is where multiprocessing should be used). So asyncio is&#xA;not a replacement for all types of asynchronous execution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Asyncio is designed around the concept of &amp;lsquo;cooperative multitasking&amp;rsquo;, so you&#xA;have complete control over when a CPU &amp;lsquo;context switch&amp;rsquo; occurs (i.e. context&#xA;switching happens at the application level and not the hardware level).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When using threads the Python scheduler is responsible for this, and so your&#xA;application may context switch at any moment (i.e. it becomes&#xA;non-deterministic).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means when using threads you&amp;rsquo;ll need to also use some form of &amp;lsquo;lock&amp;rsquo;&#xA;mechanism to prevent multiple threads from accessing/mutating shared memory&#xA;(which would otherwise subsequently cause your program to become non-thread&#xA;safe).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;a-quick-concurrent-futures-summary&#34;&gt;A quick &lt;code&gt;concurrent.futures&lt;/code&gt; summary&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The concurrent.futures module provides a high-level interface for&#xA;asynchronously executing callables. &amp;ndash;&#xA;&lt;a href=&#34;https://docs.python.org/3.8/library/concurrent.futures.html&#34; target=&#34;_blank&#34;&gt;docs.python.org/3.8/library/concurrent.futures.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;concurrent.futures&lt;/code&gt; provides a high-level abstraction for the &lt;code&gt;threading&lt;/code&gt;&#xA;and &lt;code&gt;multiprocessing&lt;/code&gt; modules, which is why we won&amp;rsquo;t discuss those modules in&#xA;detail within this post. In fact the &lt;code&gt;_thread&lt;/code&gt; module is a very low-level API&#xA;that the &lt;code&gt;threading&lt;/code&gt; module is itself built on top of (again, this is why we&#xA;won&amp;rsquo;t be covering that either).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;ve already mentioned that asyncio helps us avoid using threads so why&#xA;would we want to use &lt;code&gt;concurrent.futures&lt;/code&gt; if it&amp;rsquo;s just an abstraction on top of&#xA;threads (and multiprocessing)? Well, because not all libraries/modules/APIs&#xA;support the asyncio model.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if you use &lt;code&gt;boto3&lt;/code&gt; and interact with AWS S3, then you&amp;rsquo;ll find those&#xA;are synchronous operations. You can wrap those calls in multi-threaded code, but&#xA;it would be better to use &lt;code&gt;concurrent.futures&lt;/code&gt; as it means you not only benefit&#xA;from traditional threads but an asyncio friendly package.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;concurrent.futures&lt;/code&gt; module is also designed to interop with the asyncio&#xA;event loop, making it easier to work with a pool of threads/subprocesses within&#xA;an otherwise asyncio driven application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally you&amp;rsquo;ll also want to utilize &lt;code&gt;concurrent.futures&lt;/code&gt; when you require a&#xA;pool of threads or a pool of subprocesses, while also using a clean and modern&#xA;Python API (as apposed to the more flexible but low-level &lt;code&gt;threading&lt;/code&gt; or&#xA;&lt;code&gt;multiprocessing&lt;/code&gt; modules).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;green-threads&#34;&gt;Green threads?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many ways to achieve asynchronous programming. There&amp;rsquo;s the event loop&#xA;approach (which asyncio implements), a &amp;lsquo;callback&amp;rsquo; style historically favoured by&#xA;single-threaded languages such as JavaScript, and more traditionally there has&#xA;been a concept known as &amp;lsquo;green threads&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence a green thread looks and feels exactly like a normal thread, except&#xA;that the threads are scheduled by application code rather than by hardware (so&#xA;effectively working around the same issue of deterministic context switching as&#xA;an event loop does). But the problem of handling shared memory still exists.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s take a quick look now at what the &amp;lsquo;event loop&amp;rsquo; is, as it&amp;rsquo;s the&#xA;foundation of what makes asyncio work and why we can avoid &amp;lsquo;callback hell&amp;rsquo; and&#xA;the problems inherent with &amp;lsquo;green threads&amp;rsquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;event-loop&#34;&gt;Event Loop&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The core element of all asyncio applications is the &amp;lsquo;event loop&amp;rsquo;. The event loop&#xA;is what schedules and runs asynchronous tasks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/event-loop.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/event-loop.png&#34; alt=&#34;event loop&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;credit&#34;&gt;&#xA;  &lt;a href=&#34;https://eng.paxos.com/python-3s-killer-feature-asyncio&#34;&gt;Image Credit&lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What makes the asyncio event loop so effective is the fact that Python&#xA;implements it around &lt;a href=&#34;/posts/python-generators/&#34;&gt;generators&lt;/a&gt;. A generator&#xA;enables a function to be partially executed, then halt its execution at a&#xA;specific point, maintaining a stack of objects and exceptions, before resuming&#xA;again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve written about &lt;a href=&#34;/posts/python-generators/&#34;&gt;iterators, generators and&#xA;coroutines&lt;/a&gt; recently, so if you&amp;rsquo;re interested in&#xA;those concepts, then I&amp;rsquo;ll refer you to that post.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for more API information on the event loop, please refer to &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-eventloop.html&#34; target=&#34;_blank&#34;&gt;the&#xA;official Python&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;awaitables&#34;&gt;Awaitables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The driving force behind asyncio is the ability to schedule asynchronous&#xA;&amp;lsquo;tasks&amp;rsquo;. There are a few different types of objects in Python that help support&#xA;this, and they are generally grouped by the term &amp;lsquo;awaitable&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately, something is &lt;em&gt;awaitable&lt;/em&gt; if it can be used in an &lt;code&gt;await&lt;/code&gt; expression.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are three main types of awaitables:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Coroutines&lt;/li&gt;&#xA;&lt;li&gt;Tasks&lt;/li&gt;&#xA;&lt;li&gt;Futures&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Futures is a &lt;em&gt;low-level&lt;/em&gt; type and so you shouldn&amp;rsquo;t need to worry about&#xA;it too much if you&amp;rsquo;re not a library/framework developer (as you should be&#xA;using the higher-level abstraction APIs instead).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;coroutines&#34;&gt;Coroutines&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two closely related terms used here:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a &lt;em&gt;coroutine function&lt;/em&gt;: an &lt;code&gt;async def&lt;/code&gt; function.&lt;/li&gt;&#xA;&lt;li&gt;a &lt;em&gt;coroutine object&lt;/em&gt;: an object returned by calling a coroutine function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Generator based coroutine functions (e.g. those defined by decorating a&#xA;function with &lt;code&gt;@asyncio.coroutine&lt;/code&gt;) are superseded by the &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;&#xA;syntax, but will continue to be supported &lt;em&gt;until&lt;/em&gt; Python 3.10 &amp;ndash;&#xA;&lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-task.html#asyncio-generator-based-coro&#34; target=&#34;_blank&#34;&gt;docs.python.org/3.8/library/asyncio-task.html&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Refer to my post &amp;ldquo;&lt;a href=&#34;/posts/python-generators/&#34;&gt;iterators, generators,&#xA;coroutines&lt;/a&gt;&amp;rdquo; for more details about generator based&#xA;coroutines and their asyncio history.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;tasks&#34;&gt;Tasks&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-task.html#asyncio.Task&#34; target=&#34;_blank&#34;&gt;Tasks&lt;/a&gt; are&#xA;used to schedule coroutines &lt;em&gt;concurrently&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All asyncio applications will typically have (at least) a single &amp;lsquo;main&amp;rsquo;&#xA;entrypoint task that will be scheduled to run immediately on the event loop.&#xA;This is done using the &lt;code&gt;asyncio.run&lt;/code&gt; function (see &amp;lsquo;&lt;a href=&#34;#running-an-asyncio-program&#34;&gt;Running an asyncio&#xA;program&lt;/a&gt;&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A coroutine function is expected to be passed to &lt;code&gt;asyncio.run&lt;/code&gt;, while&#xA;&lt;em&gt;internally&lt;/em&gt; asyncio will check this using the helper function&#xA;&lt;code&gt;coroutines.iscoroutine&lt;/code&gt; (see: &lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/asyncio/runners.py#L8&#34; target=&#34;_blank&#34;&gt;source&#xA;code&lt;/a&gt;).&#xA;If not a coroutine, then an error is raised, otherwise the coroutine will be&#xA;passed to &lt;code&gt;loop.run_until_complete&lt;/code&gt; (see: &lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/asyncio/base_events.py#L599&#34; target=&#34;_blank&#34;&gt;source&#xA;code&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;run_until_complete&lt;/code&gt; function expects a &lt;a href=&#34;#futures&#34;&gt;Future&lt;/a&gt; (see below&#xA;section for what a Future is) and uses another helper function&#xA;&lt;code&gt;futures.isfuture&lt;/code&gt; to check the type provided. If not a Future, then the&#xA;low-level API &lt;code&gt;ensure_future&lt;/code&gt; is used to convert the coroutine into a Future&#xA;(see &lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/asyncio/tasks.py#L653&#34; target=&#34;_blank&#34;&gt;source&#xA;code&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://gist.github.com/1efc8dcfc0b1e9e8e8b89a4b2019f3af&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; is a&#xA;comparison of the various methods for validating if a function is a coroutine.&#xA;The results aren&amp;rsquo;t necessarily what you might expect.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In older versions of Python, if you were going to manually create your own&#xA;Future and schedule it onto the event loop, then you would have used&#xA;&lt;code&gt;asyncio.ensure_future&lt;/code&gt; (now considered to be a low-level API), but with Python&#xA;3.7+ this has been superseded by &lt;code&gt;asyncio.create_task&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally with Python 3.7, the idea of interacting with the event loop&#xA;directly (e.g. getting the event loop, creating a task with &lt;code&gt;create_task&lt;/code&gt; and&#xA;then passing it to the event loop) has been replaced with &lt;code&gt;asyncio.run&lt;/code&gt;, which&#xA;abstracts it all away for you (see &amp;lsquo;&lt;a href=&#34;#running-an-asyncio-program&#34;&gt;Running an asyncio&#xA;program&lt;/a&gt;&amp;rsquo; to understand what that means).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following APIs let you see the state of the tasks running on the event loop:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.current_task&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.all_tasks&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for other available methods on a Task object please refer to &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-task.html#asyncio.Task&#34; target=&#34;_blank&#34;&gt;the&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;futures&#34;&gt;Futures&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A Future is a low-level awaitable object that represents an eventual result of&#xA;an asynchronous operation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To use an analogy: it&amp;rsquo;s like an empty postbox. At &lt;em&gt;some point&lt;/em&gt; in the future the&#xA;postman will arrive and stick a letter into the postbox.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This API exists to enable callback-based code to be used with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;,&#xA;while&#xA;&lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-eventloop.html#asyncio.loop.run_in_executor&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;loop.run_in_executor&lt;/code&gt;&lt;/a&gt;&#xA;is an example of an asyncio low-level API function that returns a Future (see&#xA;also some of the APIs listed in &lt;a href=&#34;#concurrent-functions&#34;&gt;Concurrent Functions&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for other available methods on a Future please refer to &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-future.html#asyncio.Future&#34; target=&#34;_blank&#34;&gt;the&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;running-an-asyncio-program&#34;&gt;Running an asyncio program&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The high-level API (as per Python 3.7+) is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import asyncio&#xA;&#xA;async def foo():&#xA;    print(&amp;quot;Foo!&amp;quot;)&#xA;&#xA;async def hello_world():&#xA;    await foo()  # waits for `foo()` to complete&#xA;    print(&amp;quot;Hello World!&amp;quot;)&#xA;&#xA;asyncio.run(hello_world())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;.run&lt;/code&gt; function always creates a &lt;em&gt;new&lt;/em&gt; event loop and &lt;em&gt;closes&lt;/em&gt; it at the&#xA;end. If you were using the lower-level APIs, then this would be something you&amp;rsquo;d&#xA;have to handle manually (as demonstrated below).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;loop = asyncio.get_event_loop()&#xA;loop.run_until_complete(hello_world())&#xA;loop.close()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;running-async-code-in-the-repl&#34;&gt;Running Async Code in the REPL&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Prior to Python 3.8 you couldn&amp;rsquo;t execute async code within the standard Python&#xA;REPL (it would have required you to use the IPython REPL instead).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this with the latest version of Python you would run &lt;code&gt;python -m asyncio&lt;/code&gt;.&#xA;Once the REPL has started you don&amp;rsquo;t need to use &lt;code&gt;asyncio.run()&lt;/code&gt;, but just use&#xA;the &lt;code&gt;await&lt;/code&gt; statement directly.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;asyncio REPL 3.8.0+ (heads/3.8:5f234538ab, Dec  1 2019, 11:05:25)&#xA;&#xA;[Clang 10.0.1 (clang-1001.0.46.4)] on darwin&#xA;&#xA;Use &amp;quot;await&amp;quot; directly instead of &amp;quot;asyncio.run()&amp;quot;.&#xA;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&#xA;&#xA;&amp;gt;&amp;gt;&amp;gt; import asyncio&#xA;&amp;gt;&amp;gt;&amp;gt; async def foo():&#xA;...   await asyncio.sleep(5)&#xA;...   print(&amp;quot;done&amp;quot;)&#xA;...&#xA;&amp;gt;&amp;gt;&amp;gt; await foo()&#xA;done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice the REPL automatically executes &lt;code&gt;import asyncio&lt;/code&gt; when starting up so&#xA;we&amp;rsquo;re able to use any &lt;code&gt;asyncio&lt;/code&gt; functions (such as the &lt;code&gt;.sleep&lt;/code&gt; function)&#xA;without having to manually type that import statement ourselves.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;use-another-event-loop&#34;&gt;Use another Event Loop&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If for some reason you didn&amp;rsquo;t want to use the event loop provided by &lt;code&gt;asyncio&lt;/code&gt;&#xA;(which is a pure Python implementation), you can swap it out for another event&#xA;loop such as &lt;a href=&#34;https://github.com/MagicStack/uvloop/&#34; target=&#34;_blank&#34;&gt;uvloop&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;uvloop is a fast, drop-in replacement of the built-in asyncio event loop.&#xA;uvloop is implemented in &lt;a href=&#34;https://cython.org/&#34; target=&#34;_blank&#34;&gt;Cython&lt;/a&gt; and uses&#xA;&lt;a href=&#34;https://libuv.org/&#34; target=&#34;_blank&#34;&gt;libuv&lt;/a&gt; under the hood.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;According to the authors of uvloop, it is comparible in speed to that of&#xA;&lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; programs! I recommend reading their &lt;a href=&#34;https://magic.io/blog/uvloop-blazing-fast-python-networking/&#34; target=&#34;_blank&#34;&gt;blog&#xA;post&lt;/a&gt; about its&#xA;initial release.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to utilize uvloop then first install it with &lt;code&gt;pip install uvloop&lt;/code&gt;,&#xA;then add a call to &lt;code&gt;uvloop.install()&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;import uvloop&#xA;&#xA;async def foo():&#xA;    print(&amp;quot;Foo!&amp;quot;)&#xA;&#xA;async def hello_world():&#xA;    await foo()&#xA;    print(&amp;quot;Hello World!&amp;quot;)&#xA;&#xA;uvloop.install()&#xA;asyncio.run(hello_world())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;concurrent-functions&#34;&gt;Concurrent Functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following functions help to co-ordinate the running of functions&#xA;concurrently, and offer varying degrees of control dependant on the needs of&#xA;your application.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.gather&lt;/code&gt;: takes a sequence of awaitables, returns an aggregate list of successfully awaited values.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.shield&lt;/code&gt;: prevent an awaitable object from being cancelled.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.wait&lt;/code&gt;: wait for a sequence of awaitables, until the given &amp;lsquo;condition&amp;rsquo; is met.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.wait_for&lt;/code&gt;: wait for a single awaitable, until the given &amp;lsquo;timeout&amp;rsquo; is reached.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.as_completed&lt;/code&gt;: similar to &lt;code&gt;gather&lt;/code&gt; but returns Futures that are populated when results are ready.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;gather&lt;/code&gt; has specific options for handling errors and cancellations. For&#xA;example, if &lt;code&gt;return_exceptions: False&lt;/code&gt; then the first exception raised by one&#xA;of the awaitables is returned to the caller of &lt;code&gt;gather&lt;/code&gt;, where as if set to&#xA;&lt;code&gt;True&lt;/code&gt; then the exceptions are aggregated in the list alongside successful&#xA;results. If &lt;code&gt;gather()&lt;/code&gt; is cancelled, all submitted awaitables (that have not&#xA;completed yet) are also cancelled.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;deprecated-functions&#34;&gt;Deprecated functions&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;@asyncio.coroutine&lt;/code&gt;: removed in favour of &lt;code&gt;async def&lt;/code&gt; in Python 3.10&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;asyncio.sleep&lt;/code&gt;: the &lt;code&gt;loop&lt;/code&gt; parameter will be removed in Python 3.10&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll find in most of these APIs a &lt;code&gt;loop&lt;/code&gt; argument can be provided to&#xA;enable you to indicate the specific event loop you want to utilize). It seems&#xA;Python has deprecated this argument in 3.8, and will remove it completely in&#xA;3.10.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;gather&#34;&gt;&lt;code&gt;gather&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how to wait for multiple asynchronous tasks&#xA;to complete.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;&#xA;&#xA;async def foo(n):&#xA;    await asyncio.sleep(5)  # wait 5s before continuing&#xA;    print(f&amp;quot;n: {n}!&amp;quot;)&#xA;&#xA;&#xA;async def main():&#xA;    tasks = [foo(1), foo(2), foo(3)]&#xA;    await asyncio.gather(*tasks)&#xA;&#xA;&#xA;asyncio.run(main())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;wait&#34;&gt;&lt;code&gt;wait&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example uses the &lt;code&gt;FIRST_COMPLETED&lt;/code&gt; option, meaning whichever task&#xA;finishes first is what will be returned.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;from random import randrange&#xA;&#xA;&#xA;async def foo(n):&#xA;    s = randrange(5)&#xA;    print(f&amp;quot;{n} will sleep for: {s} seconds&amp;quot;)&#xA;    await asyncio.sleep(s)&#xA;    print(f&amp;quot;n: {n}!&amp;quot;)&#xA;&#xA;&#xA;async def main():&#xA;    tasks = [foo(1), foo(2), foo(3)]&#xA;    result = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)&#xA;    print(result)&#xA;&#xA;&#xA;asyncio.run(main())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An example output of this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1 will sleep for: 4 seconds&#xA;2 will sleep for: 2 seconds&#xA;3 will sleep for: 1 seconds&#xA;&#xA;n: 3!&#xA;&#xA;(&#xA;{&amp;lt;Task finished coro=&amp;lt;foo() done, defined at await.py:5&amp;gt; result=None&amp;gt;}, &#xA;{&#xA;&amp;lt;Task pending coro=&amp;lt;foo() running at await.py:8&amp;gt; &#xA;  wait_for=&amp;lt;Future pending cb=[&amp;lt;TaskWakeupMethWrapper object at 0x10322b468&amp;gt;()]&amp;gt;&amp;gt;, &#xA;&amp;lt;Task pending coro=&amp;lt;foo() running at await.py:8&amp;gt; &#xA;  wait_for=&amp;lt;Future pending cb=[&amp;lt;TaskWakeupMethWrapper object at 0x10322b4c8&amp;gt;()]&amp;gt;&amp;gt;&#xA;}&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;wait-for&#34;&gt;&lt;code&gt;wait_for&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how we can utilize a timeout to prevent&#xA;waiting endlessly for an asynchronous task to finish.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;&#xA;&#xA;async def foo(n):&#xA;    await asyncio.sleep(10)&#xA;    print(f&amp;quot;n: {n}!&amp;quot;)&#xA;&#xA;&#xA;async def main():&#xA;    try:&#xA;        await asyncio.wait_for(foo(1), timeout=5)&#xA;    except asyncio.TimeoutError:&#xA;        print(&amp;quot;timeout!&amp;quot;)&#xA;&#xA;&#xA;asyncio.run(main())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;asyncio.TimeoutError&lt;/code&gt; doesn&amp;rsquo;t provide any extra information so&#xA;there&amp;rsquo;s no point in trying to use it in your output (e.g. &lt;code&gt;except asyncio.TimeoutError as err: print(err)&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;as-completed&#34;&gt;&lt;code&gt;as_completed&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how &lt;code&gt;as_complete&lt;/code&gt; will yield the first task&#xA;to complete, followed by the next quickest, and the next until all tasks are&#xA;completed.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;from random import randrange&#xA;&#xA;&#xA;async def foo(n):&#xA;    s = randrange(10)&#xA;    print(f&amp;quot;{n} will sleep for: {s} seconds&amp;quot;)&#xA;    await asyncio.sleep(s)&#xA;    return f&amp;quot;{n}!&amp;quot;&#xA;&#xA;&#xA;async def main():&#xA;    counter = 0&#xA;    tasks = [foo(&amp;quot;a&amp;quot;), foo(&amp;quot;b&amp;quot;), foo(&amp;quot;c&amp;quot;)]&#xA;&#xA;    for future in asyncio.as_completed(tasks):&#xA;        n = &amp;quot;quickest&amp;quot; if counter == 0 else &amp;quot;next quickest&amp;quot;&#xA;        counter += 1&#xA;        result = await future&#xA;        print(f&amp;quot;the {n} result was: {result}&amp;quot;)&#xA;&#xA;&#xA;asyncio.run(main())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An example output of this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;c will sleep for: 9 seconds&#xA;a will sleep for: 1 seconds&#xA;b will sleep for: 0 seconds&#xA;&#xA;the quickest result was: b!&#xA;the next quickest result was: a!&#xA;the next quickest result was: c!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;create-task&#34;&gt;&lt;code&gt;create_task&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how to convert a coroutine into a Task and&#xA;schedule it onto the event loop.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;&#xA;&#xA;async def foo():&#xA;    await asyncio.sleep(10)&#xA;    print(&amp;quot;Foo!&amp;quot;)&#xA;&#xA;&#xA;async def hello_world():&#xA;    task = asyncio.create_task(foo())&#xA;    print(task)&#xA;    await asyncio.sleep(5)&#xA;    print(&amp;quot;Hello World!&amp;quot;)&#xA;    await asyncio.sleep(10)&#xA;    print(task)&#xA;&#xA;&#xA;asyncio.run(hello_world())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the above program that we use &lt;code&gt;create_task&lt;/code&gt; to convert our&#xA;coroutine function into a Task. This automatically schedules the Task to be run&#xA;on the event loop at the next available tick.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is in contrast to the lower-level API &lt;code&gt;ensure_future&lt;/code&gt; (which is the&#xA;preferred way of creating new Tasks). The &lt;code&gt;ensure_future&lt;/code&gt; function has specific&#xA;logic branches that make it useful for more input types than &lt;code&gt;create_task&lt;/code&gt; which&#xA;only supports scheduling a coroutine onto the event loop and wrapping it inside&#xA;a Task (see: &lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/asyncio/tasks.py#L653&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;ensure_future&lt;/code&gt; source&#xA;code&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The output of this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;Task pending coro=&amp;lt;foo() running at create_task.py:4&amp;gt;&amp;gt;&#xA;Hello World!&#xA;Foo!&#xA;&amp;lt;Task finished coro=&amp;lt;foo() done, defined at create_task.py:4&amp;gt; result=None&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s review the code and compare to the above output we can see&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We convert &lt;code&gt;foo()&lt;/code&gt; into a Task and then print the returned Task immediately&#xA;after it is created. So when we print the Task we can see that its status is&#xA;shown as &amp;lsquo;pending&amp;rsquo; (as it hasn&amp;rsquo;t been executed yet).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we&amp;rsquo;ll sleep for five seconds, as this will cause the &lt;code&gt;foo&lt;/code&gt; Task to now be&#xA;run (as the current Task &lt;code&gt;hello_world&lt;/code&gt; will be considered busy).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Within the &lt;code&gt;foo&lt;/code&gt; Task we also sleep, but for a &lt;em&gt;longer&lt;/em&gt; period of time than&#xA;&lt;code&gt;hello_world&lt;/code&gt;, and so the event loop will now context switch &lt;em&gt;back&lt;/em&gt; to the&#xA;&lt;code&gt;hello_world&lt;/code&gt; Task, where upon the sleep will pass and we&amp;rsquo;ll print the output&#xA;string &lt;code&gt;Hello World&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, we sleep again for ten seconds. This is just so we can give the &lt;code&gt;foo&lt;/code&gt;&#xA;Task enough time to complete and print its own output. If we didn&amp;rsquo;t do that then&#xA;the &lt;code&gt;hello_world&lt;/code&gt; task would finish and close down the event loop. The last line&#xA;of &lt;code&gt;hello_world&lt;/code&gt; is printing the &lt;code&gt;foo&lt;/code&gt; Task, where we&amp;rsquo;ll see the status of the&#xA;&lt;code&gt;foo&lt;/code&gt; Task will now show as  &amp;lsquo;finished&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;callbacks&#34;&gt;Callbacks&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with a Task, which really is a Future, then you have the ability to&#xA;execute a &amp;lsquo;callback&amp;rsquo; function once the Future has a value set on it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates this by modifying the previous&#xA;&lt;a href=&#34;#create_task&#34;&gt;&lt;code&gt;create_task&lt;/code&gt;&lt;/a&gt; example code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;&#xA;&#xA;async def foo():&#xA;    await asyncio.sleep(10)&#xA;    return &amp;quot;Foo!&amp;quot;&#xA;&#xA;&#xA;def got_result(future):&#xA;    print(f&amp;quot;got the result! {future.result()}&amp;quot;)&#xA;&#xA;&#xA;async def hello_world():&#xA;    task = asyncio.create_task(foo())&#xA;    task.add_done_callback(got_result)&#xA;    print(task)&#xA;    await asyncio.sleep(5)&#xA;    print(&amp;quot;Hello World!&amp;quot;)&#xA;    await asyncio.sleep(10)&#xA;    print(task)&#xA;&#xA;&#xA;asyncio.run(hello_world())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the above program we add a new &lt;code&gt;got_result&lt;/code&gt; function that expects to&#xA;receive a Future type, and thus calls &lt;code&gt;.result()&lt;/code&gt; on the Future.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also notice that to get this function to be called, we pass it to&#xA;&lt;code&gt;.add_done_callback()&lt;/code&gt; which is called on the Task returned by &lt;code&gt;create_task&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The output of this program is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;Task pending coro=&amp;lt;foo() running at gather.py:4&amp;gt; cb=[got_result() at gather.py:9]&amp;gt;&#xA;Hello World!&#xA;got the result! Foo!&#xA;&amp;lt;Task finished coro=&amp;lt;foo() done, defined at gather.py:4&amp;gt; result=&#39;Foo!&#39;&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;pools&#34;&gt;Pools&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with lots of concurrent operations it might be wise to utilize a&#xA;&amp;lsquo;pool&amp;rsquo; of threads (and/or subprocesses) to prevent exhausting your application&amp;rsquo;s&#xA;host resources.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where the &lt;code&gt;concurrent.futures&lt;/code&gt; module comes in. It provides a concept&#xA;referred to as an Executor to help with this and which can be run standalone or&#xA;be integrated into an existing asyncio event loop (see: &lt;a href=&#34;https://docs.python.org/3.8/library/concurrent.futures.html#concurrent.futures.Executor&#34; target=&#34;_blank&#34;&gt;Executor&#xA;documentation&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;executors&#34;&gt;Executors&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two types of &amp;lsquo;executors&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/concurrent.futures.html#threadpoolexecutor&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;ThreadPoolExecutor&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3.8/library/concurrent.futures.html#processpoolexecutor&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;ProcessPoolExecutor&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at the first way to execute code within one of these executors, by&#xA;using an asyncio event loop to schedule the running of the executor.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this you need to call the event loop&amp;rsquo;s &lt;code&gt;.run_in_executor()&lt;/code&gt; function and&#xA;pass in the executor type as the first argument. If &lt;code&gt;None&lt;/code&gt; is provided, then the&#xA;&lt;em&gt;default&lt;/em&gt; executor is used (which is the &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example is copied verbatim from the &lt;a href=&#34;https://docs.python.org/3.8/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools&#34; target=&#34;_blank&#34;&gt;Python&#xA;documentation&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;import concurrent.futures&#xA;&#xA;&#xA;def blocking_io():&#xA;    # File operations (such as logging) can block the&#xA;    # event loop: run them in a thread pool.&#xA;    with open(&amp;quot;/dev/urandom&amp;quot;, &amp;quot;rb&amp;quot;) as f:&#xA;        return f.read(100)&#xA;&#xA;&#xA;def cpu_bound():&#xA;    # CPU-bound operations will block the event loop:&#xA;    # in general it is preferable to run them in a&#xA;    # process pool.&#xA;    return sum(i * i for i in range(10 ** 7))&#xA;&#xA;&#xA;async def main():&#xA;    loop = asyncio.get_running_loop()&#xA;&#xA;    # 1. Run in the default loop&#39;s executor:&#xA;    result = await loop.run_in_executor(None, blocking_io)&#xA;    print(&amp;quot;default thread pool&amp;quot;, result)&#xA;&#xA;    # 2. Run in a custom thread pool:&#xA;    with concurrent.futures.ThreadPoolExecutor() as pool:&#xA;        result = await loop.run_in_executor(pool, blocking_io)&#xA;        print(&amp;quot;custom thread pool&amp;quot;, result)&#xA;&#xA;    # 3. Run in a custom process pool:&#xA;    with concurrent.futures.ProcessPoolExecutor() as pool:&#xA;        result = await loop.run_in_executor(pool, cpu_bound)&#xA;        print(&amp;quot;custom process pool&amp;quot;, result)&#xA;&#xA;&#xA;asyncio.run(main())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The second way to execute code within one of these executors is to send the code&#xA;to be executed directly to the pool. This means we don&amp;rsquo;t have to acquire the&#xA;current event loop to pass the pool into it (as the earlier example&#xA;demonstrated), but it comes with a caveat which is the parent program won&amp;rsquo;t wait&#xA;for the task to be completed unless you explicitly tell it to (which I&amp;rsquo;ll&#xA;demonstrate next).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind, let&amp;rsquo;s take a look at this alternative approach. It involves&#xA;calling the executor&amp;rsquo;s &lt;code&gt;submit()&lt;/code&gt; method:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import concurrent.futures&#xA;import time&#xA;&#xA;&#xA;def slow_op(*args):&#xA;    print(f&amp;quot;arguments: {args}&amp;quot;)&#xA;    time.sleep(5)&#xA;    print(&amp;quot;slow operation complete&amp;quot;)&#xA;    return 123&#xA;&#xA;&#xA;def do_something():&#xA;    with concurrent.futures.ProcessPoolExecutor() as pool:&#xA;        future = pool.submit(slow_op, &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;)&#xA;&#xA;        for fut in concurrent.futures.as_completed([future]):&#xA;            assert future.done() and not future.cancelled()&#xA;            print(f&amp;quot;got the result from slow_op: {fut.result()}&amp;quot;)&#xA;&#xA;&#xA;if __name__ == &amp;quot;__main__&amp;quot;:&#xA;    print(&amp;quot;program started&amp;quot;)&#xA;    do_something()&#xA;    print(&amp;quot;program complete&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be careful with a global process executor (e.g. placing something like&#xA;&lt;code&gt;PROCESS_POOL = concurrent.futures.ProcessPoolExecutor()&lt;/code&gt; within the global&#xA;scope and using that reference within our &lt;code&gt;do_something()&lt;/code&gt; function) as this&#xA;means when the program is copied into a &lt;em&gt;new&lt;/em&gt; process you&amp;rsquo;ll get an error from&#xA;the Python interpreter about a leaked semaphore. This is why I create the&#xA;process pool executor within a function.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;One thing worth noting here is that if we hadn&amp;rsquo;t used the &lt;code&gt;with&lt;/code&gt; statement (like&#xA;we do in the above example) it would mean we&amp;rsquo;d not be shutting down the pool&#xA;once it has finished its work, and so (depending on if your program continues&#xA;running) you may discover resources aren&amp;rsquo;t being cleaned up.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To solve that problem you can call the &lt;code&gt;.shutdown()&lt;/code&gt; method which is exposed to&#xA;both types of executors via its parent class &lt;code&gt;concurrent.futures.Executor&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example that does that, but now using the threadpool executor:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import concurrent.futures&#xA;&#xA;THREAD_POOL = concurrent.futures.ThreadPoolExecutor(max_workers=5)&#xA;&#xA;&#xA;def slow_op(*args):&#xA;    with open(&amp;quot;/dev/urandom&amp;quot;, &amp;quot;rb&amp;quot;) as f:&#xA;        return f.read(100000)&#xA;&#xA;&#xA;def do_something():&#xA;    future = THREAD_POOL.submit(slow_op, &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;)&#xA;&#xA;    THREAD_POOL.shutdown()&#xA;&#xA;    assert future.done() and not future.cancelled()&#xA;&#xA;    print(f&amp;quot;got the result from slow_op: {len(future.result())}&amp;quot;)&#xA;&#xA;&#xA;if __name__ == &amp;quot;__main__&amp;quot;:&#xA;    print(&amp;quot;program started&amp;quot;)&#xA;    do_something()&#xA;    print(&amp;quot;program complete&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Pay attention to the placement of the call to &lt;code&gt;.shutdown()&lt;/code&gt;. We no longer have&#xA;any code to handle waiting for the task to complete. You might have expected&#xA;calling &lt;code&gt;.shutdown()&lt;/code&gt; and then immediately checking if the task is complete&#xA;(e.g. &lt;code&gt;assert future.done()&lt;/code&gt;) to cause an error to be raised as the future is&#xA;unlikely to be finished.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;remember also if you call &lt;code&gt;.done()&lt;/code&gt; on a future when a value has not yet&#xA;been set, then you&amp;rsquo;ll see an exception such as &lt;code&gt;asyncio.InvalidStateError&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But no error is raised, and the future is indeed considered &amp;lsquo;done&amp;rsquo; by the time&#xA;we check it. This is because the shutdown method has a single argument defined&#xA;called &lt;code&gt;wait&lt;/code&gt; and its default value is set to &lt;code&gt;True&lt;/code&gt;, which means it would wait&#xA;for all scheduled tasks to complete before shutting down the executor pool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thus the &lt;code&gt;.shutdown()&lt;/code&gt; method is a synchronization call (i.e. it ensures all&#xA;tasks are complete before shutting down, and thus we can guarantee all results&#xA;will be available).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if we had passed &lt;code&gt;.shutdown(wait=False)&lt;/code&gt; instead, then the call to&#xA;&lt;code&gt;future.done()&lt;/code&gt; would have raised an exception (as the scheduled task would&#xA;still be running as the threadpool was being closed), and so in that case we&amp;rsquo;d&#xA;need to ensure that we use another mechanism for acquiring the results of the&#xA;scheduled tasks (such as &lt;code&gt;concurrent.futures.as_completed&lt;/code&gt; or&#xA;&lt;code&gt;concurrent.futures.wait&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;asyncio-future-vs-concurrent-futures-future&#34;&gt;&lt;code&gt;asyncio.Future&lt;/code&gt; vs &lt;code&gt;concurrent.futures.Future&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One final thing to mention is that a &lt;code&gt;concurrent.futures.Future&lt;/code&gt; object is&#xA;&lt;em&gt;different&lt;/em&gt; from an &lt;code&gt;asyncio.Future&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An &lt;code&gt;asyncio.Future&lt;/code&gt; is intended to be used with the asyncio&amp;rsquo;s event loop, and is&#xA;&lt;a href=&#34;#awaitables&#34;&gt;&lt;em&gt;awaitable&lt;/em&gt;&lt;/a&gt;. A &lt;code&gt;concurrent.futures.Future&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; awaitable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the &lt;code&gt;.run_in_executor()&lt;/code&gt; method of an event loop will provide the&#xA;necessary interoperability between the two future types by wrapping the&#xA;&lt;code&gt;concurrent.futures.Future&lt;/code&gt; type in a call to&#xA;&lt;a href=&#34;#asyncio-wrap-future&#34;&gt;&lt;code&gt;asyncio.wrap_future&lt;/code&gt;&lt;/a&gt; (see next section for details).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;asyncio-wrap-future&#34;&gt;&lt;code&gt;asyncio.wrap_future&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Since Python 3.5 we can use &lt;code&gt;asyncio.wrap_future&lt;/code&gt; to convert a&#xA;&lt;code&gt;concurrent.futures.Future&lt;/code&gt; to an &lt;code&gt;asyncio.Future&lt;/code&gt;. An example of this can be&#xA;seen below&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import asyncio&#xA;import random&#xA;from concurrent.futures import ThreadPoolExecutor&#xA;from time import sleep&#xA;&#xA;&#xA;def return_after_5_secs(message):&#xA;    sleep(5)&#xA;    return message&#xA;&#xA;&#xA;pool = ThreadPoolExecutor(3)&#xA;&#xA;&#xA;async def doit():&#xA;    identify = random.randint(1, 100)&#xA;    future = pool.submit(return_after_5_secs, (f&amp;quot;result: {identify}&amp;quot;))&#xA;    awaitable = asyncio.wrap_future(future)&#xA;    print(f&amp;quot;waiting result: {identify}&amp;quot;)&#xA;    return await awaitable&#xA;&#xA;&#xA;async def app():&#xA;    # run some stuff multiple times&#xA;    tasks = [doit(), doit()]&#xA;&#xA;    result = await asyncio.gather(*tasks)&#xA;    print(result)&#xA;&#xA;print(&amp;quot;waiting app&amp;quot;)&#xA;asyncio.run(app())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;waiting app&#xA;waiting result: 62&#xA;waiting result: 83&#xA;&#xA;# ...five seconds pass by...&#xA;&#xA;[&#39;result: 62&#39;, &#39;result: 83&#39;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-asyncio/</guid>
      <link>https://www.integralist.co.uk/posts/python-asyncio/</link>
      <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
      <title>Guide to Concurrency in Python with Asyncio</title>
    </item>
    <item>
      <description>&lt;p&gt;I found myself recently trying to recall specific details of how &lt;a href=&#34;https://blog.golang.org/go-slices-usage-and-internals&#34; target=&#34;_blank&#34;&gt;slices&lt;/a&gt; work when needing to do something that meant I wanted to &lt;em&gt;not&lt;/em&gt; mutate the underlying array data structure of the slice I was working with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the reason for why I wanted to do that isn&amp;rsquo;t important. What&amp;rsquo;s motivating this write-up is my want for a good reference document (not saying the official go blog isn&amp;rsquo;t a good reference, but I have my own things I like to focus in on in these situations).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;composite-types&#34;&gt;Composite Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s recap on what we&amp;rsquo;re talking about when we say &amp;ldquo;array&amp;rdquo; and &amp;ldquo;slice&amp;rdquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Array&lt;/strong&gt;: fixed-length data structure, zero-indexed, contains same type&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Slice&lt;/strong&gt;: variable-length sequence, contains same type&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;arrays&#34;&gt;Arrays&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An array uses subscript notation to access elements, and is zero-indexed. Here is an example of both those concepts:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [3]string{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;}&#xA;&#xA;fmt.Println(a[1]) // &amp;quot;b&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you define an array without using the &amp;lsquo;literal&amp;rsquo; syntax (as demonstrated in the above example program), then the values will be initialized with the zero value of the given type, for example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;var a [3]string&#xA;&#xA;fmt.Printf(&amp;quot;%#v&amp;quot;, a) // [3]string{&amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The size of the array is actually part of its &amp;lsquo;type&amp;rsquo; definition, for example the following two arrays have unique types:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [3]string{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;}&#xA;b := [2]string{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;}&#xA;&#xA;fmt.Printf(&amp;quot;a: %T, b: %T&amp;quot;, a, b) // a: [3]string, b: [2]string&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to have to count the number of elements you&amp;rsquo;re defining, then you can use an ellipsis &lt;code&gt;...&lt;/code&gt; instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [...]int{1, 2, 3}&#xA;&#xA;fmt.Printf(&amp;quot;%T %#v&amp;quot;, a, a) // [3]int [3]int{1, 2, 3}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how the output of the above program inserts the calculated length of the array.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As arrays are fixed-length, it means they cannot be resized once full.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Arrays are also &amp;lsquo;copied&amp;rsquo; when being passed into a function. This means if a function modifies a given array, it&amp;rsquo;s actually only modifying a &lt;em&gt;copy&lt;/em&gt; of the array and not the original (i.e. go doesnt use &amp;lsquo;pass-by-reference&amp;rsquo; semantics like some other languages).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If dealing we an array data structure, remember you&amp;rsquo;ll need to pass a pointer to it if you require a function to be able to modify the original array in memory.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;slices&#34;&gt;Slices&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A slice is a lightweight data structure that provides access to a subsequence (or &amp;lsquo;window&amp;rsquo; view) of an underlying array.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The slice data structure consists of the following fields:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;ptr&lt;/strong&gt;: pointer to array.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;len&lt;/strong&gt;: length of slice (number of elements it contains).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;cap&lt;/strong&gt;: capacity of slice (number of elements in array, starting from the first element in the slice).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a slice cannot grow larger than its capacity, nor can you reslice a slice to attempt to access earlier elements in the array.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is an example program that creates an array and then makes a slice of a subsequence of the original array:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [3]int{1, 2, 3}&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\n&amp;quot;, a, a)&#xA;&#xA;s := a[1:]&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n&amp;quot;, s, s)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output from the above code would be as follows (notice how the slice provides a narrower &amp;lsquo;view&amp;rsquo; of the original array):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;array: [3]int&#xA;       [3]int{1, 2, 3}&#xA;&#xA;slice: []int&#xA;       []int{2, 3}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice that a slice &amp;lsquo;type&amp;rsquo; looks the same as an array&amp;rsquo;s, but just omits a length (e.g. slice: &lt;code&gt;[]int&lt;/code&gt;, array: &lt;code&gt;[3]int&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Slices, much like arrays, cannot dynamically grow larger at runtime. When a slice is full we must create a &lt;em&gt;new&lt;/em&gt; slice, which requires the use of go&amp;rsquo;s builtin functions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When modifying a slice you are infact modifying the underlying array, as demonstrated below:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [3]int{1, 2, 3}&#xA;s := a[1:]&#xA;&#xA;s[0] = 4&#xA;&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\n&amp;quot;, a, a)&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n&amp;quot;, s, s)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code results in the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;array: [3]int&#xA;       [3]int{1, 4, 3}&#xA;&#xA;slice: []int&#xA;       []int{4, 3}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice &lt;em&gt;both&lt;/em&gt; the slice and the underlying array have been updated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although a lot of people refer to this as &amp;ldquo;updating a slice&amp;rdquo; when talking about their code, I personally think it&amp;rsquo;s best not to think of these as two distinct pieces of data. The array holds the data and the slice is just a language abstraction that enables us to control how we view that data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, it&amp;rsquo;s important to realize that because a slice contains a pointer to an underlying array, it means &lt;em&gt;multiple&lt;/em&gt; slices can point to the &lt;em&gt;same&lt;/em&gt; array in memory (as demonstrated below).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [3]int{1, 2, 3}&#xA;s1 := a[:2]&#xA;s2 := a[1:]&#xA;&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\n&amp;quot;, a, a)&#xA;fmt.Printf(&amp;quot;slice1: %T\n\t%#v\n\n&amp;quot;, s1, s1)&#xA;fmt.Printf(&amp;quot;slice2: %T\n\t%#v\n\n&amp;quot;, s2, s2)&#xA;&#xA;// make modification via the first slice&#xA;s1[1] = 4&#xA;&#xA;fmt.Print(&amp;quot;---\n\n&amp;quot;)&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\n&amp;quot;, a, a)&#xA;fmt.Printf(&amp;quot;slice1: %T\n\t%#v\n\n&amp;quot;, s1, s1)&#xA;fmt.Printf(&amp;quot;slice2: %T\n\t%#v\n\n&amp;quot;, s2, s2)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the above program is shown below. Notice how the two slices, &lt;code&gt;s1&lt;/code&gt; and &lt;code&gt;s2&lt;/code&gt; both point at the &lt;em&gt;same&lt;/em&gt; underlying array and so although we make a modification via the first slice we can see that both slices will highlight the changed value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;array:  [3]int&#xA;    [3]int{1, 2, 3}&#xA;&#xA;slice1: []int&#xA;    []int{1, 2}&#xA;&#xA;slice2: []int&#xA;    []int{2, 3}&#xA;&#xA;---&#xA;&#xA;array:  [3]int&#xA;    [3]int{1, 4, 3}&#xA;&#xA;slice1: []int&#xA;    []int{1, 4}&#xA;&#xA;slice2: []int&#xA;    []int{4, 3}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;append&#34;&gt;Append&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll find in a lot of situations code that needs to append data to a slice. This results in code that uses the builtin &lt;code&gt;append&lt;/code&gt; function, but interestingly will nearly always reassign the returned value back to the slice variable itself:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [...]int{1, 2, 3, 4, 5}&#xA;s := a[1:]&#xA;&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n\n&amp;quot;, a, a, len(a), cap(a))&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n\n&amp;quot;, s, s, len(s), cap(s))&#xA;&#xA;s = append(s, 6)&#xA;&#xA;fmt.Printf(&amp;quot;array:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n\n&amp;quot;, a, a, len(a), cap(a))&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n\n&amp;quot;, s, s, len(s), cap(s))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above program we have an array that contains five elements. We take a slice of it which is the last four elements. We then attempt to append a new value (&lt;code&gt;6&lt;/code&gt;) to the slice (which should mean appending it to the underlying array). The output of that program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;array:  [5]int&#xA;    [5]int{1, 2, 3, 4, 5}&#xA;    len: 5&#xA;    cap: 5&#xA;&#xA;slice:  []int&#xA;    []int{2, 3, 4, 5}&#xA;    len: 4&#xA;    cap: 4&#xA;&#xA;array:  [5]int&#xA;    [5]int{1, 2, 3, 4, 5}&#xA;    len: 5&#xA;    cap: 5&#xA;&#xA;slice:  []int&#xA;    []int{2, 3, 4, 5, 6}&#xA;    len: 5&#xA;    cap: 8&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;append&lt;/code&gt; function &lt;em&gt;always&lt;/em&gt; returns a new slice.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Notice how &lt;code&gt;s&lt;/code&gt; is showing an updated &amp;lsquo;view&amp;rsquo; (e.g. &lt;code&gt;2, 3, 4, 5, 6&lt;/code&gt;). What&amp;rsquo;s interesting here is the new slice must have also resulted in a new array being allocated (and subsequently the new slice is pointing to it) because the original array (&lt;code&gt;a&lt;/code&gt;) isn&amp;rsquo;t showing the appended value (&lt;code&gt;6&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we can check this with some overly complicated code that &amp;lsquo;reflects&amp;rsquo; into the internal go code (this will enable us to locate the slice&amp;rsquo;s pointer and to dereference that pointer to access the underlying array):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;s := []int{1, 2, 3, 4}&#xA;&#xA;hdr := (*reflect.SliceHeader)(unsafe.Pointer(&amp;amp;s))&#xA;data := *(*[4]int)(unsafe.Pointer(hdr.Data))&#xA;&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n&amp;quot;, s, s, len(s), cap(s))&#xA;fmt.Printf(&amp;quot;hdr: %#v\n&amp;quot;, hdr)   // &amp;amp;reflect.SliceHeader{Data:0x40e020, Len:4, Cap:4}&#xA;fmt.Printf(&amp;quot;data: %#v\n&amp;quot;, data) // [4]int{1, 2, 3, 4}&#xA;&#xA;s = append(s, 5)&#xA;&#xA;hdr2 := (*reflect.SliceHeader)(unsafe.Pointer(&amp;amp;s))&#xA;data2 := *(*[8]int)(unsafe.Pointer(hdr.Data))&#xA;&#xA;fmt.Printf(&amp;quot;slice:  %T\n\t%#v\n\tlen: %d\n\tcap: %d\n&amp;quot;, s, s, len(s), cap(s))&#xA;fmt.Printf(&amp;quot;hdr2: %#v\n&amp;quot;, hdr2)   // &amp;amp;reflect.SliceHeader{Data:0x45e020, Len:5, Cap:8}&#xA;fmt.Printf(&amp;quot;data2: %#v\n&amp;quot;, data2) // [8]int{1, 2, 3, 4, 5, 0, 0, 0}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;s := []int{1, 2, 3, 4}&lt;/code&gt; causes an underlying array to be created and then referened by the slice we defined.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The output of the above program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;slice:  []int&#xA;    []int{1, 2, 3, 4}&#xA;    len: 4&#xA;    cap: 4&#xA;&#xA;hdr: &amp;amp;reflect.SliceHeader{Data:0x40e020, Len:4, Cap:4}&#xA;data: [4]int{1, 2, 3, 4}&#xA;&#xA;slice:  []int&#xA;    []int{1, 2, 3, 4, 5}&#xA;    len: 5&#xA;    cap: 8&#xA;&#xA;hdr: &amp;amp;reflect.SliceHeader{Data:0x45e020, Len:5, Cap:8}&#xA;data: [8]int{1, 2, 3, 4, 5, 0, 0, 0}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see the &lt;code&gt;Data&lt;/code&gt; field on the &lt;code&gt;SliceHeader&lt;/code&gt; is pointing to a different memory address!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can also see that the capacity of the slice (&lt;code&gt;cap&lt;/code&gt;) has increased to double! This demonstrates what&amp;rsquo;s happening &amp;lsquo;behind-the-scenes&amp;rsquo;, and is similar to how resizing an array is done in other languages (i.e. you create a new array at double the size of the old array, then you append the new values until that new array is full and the process repeats).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what has happened is that &lt;code&gt;append&lt;/code&gt; has returned a &lt;em&gt;new&lt;/em&gt; slice (which is expected), but that the slice is now pointing to a &lt;em&gt;new&lt;/em&gt; underlying array. This is the primary reason why when appending a value to a slice you&amp;rsquo;ll see the slice variable is updated to the return value of &lt;code&gt;append&lt;/code&gt;: because we don&amp;rsquo;t know (unless we do some inspection of the returned slice) whether the underlying array has been copied to a new array in memory.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;caveat-of-appending&#34;&gt;Caveat of Appending&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If the underlying array had enough capacity for the appended value(s), then &lt;code&gt;append&lt;/code&gt; would have still returned a new slice (because remember a slice cannot grow beyond its defined capacity) but the underlying array would still be the same array in memory. Let&amp;rsquo;s see an example of that below:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;a := [6]int{1, 2, 3, 4, 5, 6}&#xA;s := a[1:4]&#xA;x := append(s, 0)&#xA;&#xA;fmt.Printf(&amp;quot;array:    %T\n\t  %#v\n\t  len: %d\n\t  cap: %d\n\n&amp;quot;, a, a, len(a), cap(a))&#xA;fmt.Printf(&amp;quot;slice1 s: %T\n\t  %#v\n\t  len: %d\n\t  cap: %d\n\n&amp;quot;, s, s, len(s), cap(s))&#xA;fmt.Printf(&amp;quot;slice2 x: %T\n\t  %#v\n\t  len: %d\n\t  cap: %d\n\n&amp;quot;, x, x, len(x), cap(x))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of that program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;array:    [6]int&#xA;      [6]int{1, 2, 3, 4, 0, 6}&#xA;      len: 6&#xA;      cap: 6&#xA;&#xA;slice1 s: []int&#xA;      []int{2, 3, 4}&#xA;      len: 3&#xA;      cap: 5&#xA;&#xA;slice2 x: []int&#xA;      []int{2, 3, 4, 0}&#xA;      len: 4&#xA;      cap: 5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how the first slice &lt;code&gt;s&lt;/code&gt; has a length of &lt;code&gt;3&lt;/code&gt; and a capacity of &lt;code&gt;5&lt;/code&gt;. That is because when we created the slice we specified explicitly we wanted only three elements (&lt;code&gt;1:4&lt;/code&gt;) and that the slice&amp;rsquo;s capacity is derived from the number of elements in the underlying array &lt;em&gt;starting from&lt;/em&gt; the first element referenced within the slice).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning the first element in the slice is &lt;code&gt;2&lt;/code&gt; and counting from there within the underlying array would result in a capacity of &lt;code&gt;5&lt;/code&gt; (e.g. &lt;code&gt;2, 3, 4, 5, 6&lt;/code&gt; is five elements).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when we call &lt;code&gt;append&lt;/code&gt; on &lt;code&gt;s&lt;/code&gt; we know that &lt;code&gt;append&lt;/code&gt; will always return a new slice and so we assign that new slice to a different variable &lt;code&gt;x&lt;/code&gt;. We can see for &lt;code&gt;x&lt;/code&gt; the length is one element longer because of the append (e.g. we appended the value &lt;code&gt;0&lt;/code&gt;) but the capacity is still &lt;code&gt;5&lt;/code&gt; meaning there is more room in the underlying array and so we don&amp;rsquo;t create a new array nor update the slice pointer to that new array.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s really interesting here is that the appending of the value &lt;code&gt;0&lt;/code&gt; to the first slice has caused the underlying array to be modified in a potentially unexpected way!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By that I mean, we can see the underlying array has now replaced the element value &lt;code&gt;5&lt;/code&gt; with &lt;code&gt;0&lt;/code&gt; instead of having &lt;code&gt;0&lt;/code&gt; appended to the end of it. You might have expected a new array to be created (because &lt;em&gt;really&lt;/em&gt; the underlying array has a length of &lt;code&gt;6&lt;/code&gt; and so an array with elements &lt;code&gt;1, 2, 3, 4, 5, 6, 0&lt;/code&gt; would be a length of &lt;em&gt;seven&lt;/em&gt;, thus not enough capacity in the array).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But because of how slices work, and its capacity is determined by the number of elements in the underlying array &lt;em&gt;starting from&lt;/em&gt; the first element referenced by the slice, it means when we append to the underlying array, we are doing so from the perspective of the underlying array ending at the element value &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Yes, this is confusing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See the &lt;a href=&#34;https://tour.golang.org/moretypes/11&#34; target=&#34;_blank&#34;&gt;go tour for more examples&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there&amp;rsquo;s also a &lt;em&gt;gotcha&lt;/em&gt; which is worth being aware of, and is related to the fact that slices point to the same underlying array, which occurs when the slice modifications don&amp;rsquo;t change the array&amp;rsquo;s capacity. See &lt;a href=&#34;https://yourbasic.org/golang/gotcha-append/&#34; target=&#34;_blank&#34;&gt;https://yourbasic.org/golang/gotcha-append/&lt;/a&gt; for details.&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-arrays-and-slices/</guid>
      <link>https://www.integralist.co.uk/posts/go-arrays-and-slices/</link>
      <pubDate>Sun, 17 Nov 2019 00:00:00 +0000</pubDate>
      <title>Go Arrays and Slices</title>
    </item>
    <item>
      <description>&lt;p&gt;Privacy is becoming more and more important in our modern world. We&amp;rsquo;re constantly tracked and having our movements sold to advertisers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even more so our privacy becomes a &lt;em&gt;necessity&lt;/em&gt; if we find ourselves doing things that could get us arrested (or even killed), such as being a journalist or a whistleblower.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am lucky enough to not suffer from such necessity, but wherever possible I do like to have &lt;em&gt;control&lt;/em&gt; over my web browsing and other online habits.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What follows are some tools that I use to try and limit my exposure to the internet. This isn&amp;rsquo;t a &amp;lsquo;how to be 100% anonymous&amp;rsquo; guide, but maybe some of these tools will be of interest to you.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dns&#34;&gt;DNS&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you make a request for an online resource (for example this web page), your computer had to first convert the domain &lt;code&gt;integralist.co.uk&lt;/code&gt; into an IP so that it could lookup the resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve discussed &lt;a href=&#34;/posts/dns-101/&#34;&gt;how DNS works previously&lt;/a&gt; so I wont dive into the details of it here, but suffice to say the whole process of resolving the domain name to an IP address is something that happens unencrypted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That means every resource you try to access will be known by your ISP, and anyone else for that matter who are snooping on the packets crossing over the network.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, a &amp;lsquo;man-in-the-middle&amp;rsquo; (MITM) could modify DNS responses in such a way as to direct you to the wrong location (e.g. &lt;a href=&#34;https://www.phishing.org/what-is-phishing&#34; target=&#34;_blank&#34;&gt;phishing&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid these concerns you should utilize an encrypted connection to a DNS resolver. There are organizations, such as Cloudflare and Google, who offer this for free (that in itself is usually something to pay attention to for those who are very security minded).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are currently two forms that this type of encryption can take:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;DNS over TLS (DoT)&lt;/li&gt;&#xA;&lt;li&gt;DNS over HTTPS (DoH)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are arguments over which is better, see &lt;a href=&#34;https://www.thesslstore.com/blog/dns-over-tls-vs-dns-over-https/&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt; for a breakdown of what it all means.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here are some useful links to Cloudflare and Google if you&amp;rsquo;re interested in their services:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Cloudflare:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developers.cloudflare.com/1.1.1.1/dns-over-tls/&#34; target=&#34;_blank&#34;&gt;DNS over TLS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developers.cloudflare.com/1.1.1.1/dns-over-https/&#34; target=&#34;_blank&#34;&gt;DNS over HTTPS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Google:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developers.google.com/speed/public-dns/docs/dns-over-tls&#34; target=&#34;_blank&#34;&gt;DNS over TLS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developers.google.com/speed/public-dns/docs/doh/&#34; target=&#34;_blank&#34;&gt;DNS over HTTPS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;vpn&#34;&gt;VPN&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;VPN stands for &amp;ldquo;virtual private network&amp;rdquo;, and is used to encrypt your internet traffic. This means no one, not even your ISP can see what resources you are requesting. All your ISP will see is you make a request to a VPN and from there you have established a secure &amp;lsquo;tunnel&amp;rsquo; to pass data back-and-forth.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to ensure your chosen VPN doesn&amp;rsquo;t &lt;a href=&#34;https://www.expressvpn.com/dns-leak-test&#34; target=&#34;_blank&#34;&gt;leak DNS requests&lt;/a&gt;, which can occur if your VPN doesn&amp;rsquo;t offer a feature such as a &amp;lsquo;&lt;a href=&#34;https://www.expressvpn.com/features/network-lock&#34; target=&#34;_blank&#34;&gt;network kill switch&lt;/a&gt;&amp;rsquo; (or &amp;lsquo;network lock&amp;rsquo;). Typically this is handled by the VPN software you download and run on your computer.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are &lt;a href=&#34;https://restoreprivacy.com/vpn-test/&#34; target=&#34;_blank&#34;&gt;online tools&lt;/a&gt; available that help you verify your VPN isn&amp;rsquo;t leaking data.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Using a VPN also means your IP is protected and can&amp;rsquo;t be identified because resources that are requested are actually requested from the VPN server(s). IP protection can also be increased if you utilize a request pattern such as &lt;a href=&#34;https://nordvpn.com/features/double-vpn/&#34; target=&#34;_blank&#34;&gt;Double Hop&lt;/a&gt; or an extra service such as &lt;a href=&#34;#tor&#34;&gt;Tor&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically you pay for a VPN, although in some cases you might find one that offers a free tier (e.g. &lt;a href=&#34;https://windscribe.com/&#34; target=&#34;_blank&#34;&gt;Windscribe&lt;/a&gt;). Although in the case of Windscribe that requires them to &lt;a href=&#34;https://windscribe.com/features/no-logs&#34; target=&#34;_blank&#34;&gt;monitor your logs&lt;/a&gt; in order to distinguish between free tier users who are abusing their service.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are &lt;a href=&#34;https://thatoneprivacysite.net/&#34; target=&#34;_blank&#34;&gt;online resources&lt;/a&gt; for comparing different VPNs, which can be useful for helping you choose who to use.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Tracking bandwidth might be a concern to you if you&amp;rsquo;re overly security-minded, or it might be an acceptable trade-off for utilizing a free service. I personally believe that you get what you pay for, and a VPN is usually money well spent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Paying for a VPN doesn&amp;rsquo;t have to be expensive though. I pay £6 a month which is acceptable considering I encrypt &lt;em&gt;all&lt;/em&gt; my traffic, but I can appreciate that this might still be too much money for some people depending on circumstance.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can find VPNs for as cheap as £1 a month (e.g. Windscribe&amp;rsquo;s custom built plans) or from as low as £2.99 with &lt;a href=&#34;https://nordvpn.com/&#34; target=&#34;_blank&#34;&gt;NordVPN&lt;/a&gt; depending on the length of the plan you select.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tor&#34;&gt;Tor&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.torproject.org/&#34; target=&#34;_blank&#34;&gt;Tor (aka. The Onion Router)&lt;/a&gt; is a free service that directs your requested resource through multiple servers (much like the layers of an onion). The servers are chosen at random and increase your privacy by obfuscating the origin of the request through the use of encryption.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Tor does not &lt;em&gt;replace&lt;/em&gt; a VPN. Tor only anonymizes your web browsing, whereas a VPN encrypts all internet traffic (e.g. locally running desktop applications, to terminal command line applications etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using Tor with a VPN &lt;a href=&#34;https://www.expressvpn.com/how-to-use-vpn/tor-vpn&#34; target=&#34;_blank&#34;&gt;is possible&lt;/a&gt; but only really for those who require &lt;em&gt;complete&lt;/em&gt; privacy (arguably not possible without a lot of effort).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For most typical users who want to protect their privacy and online behaviours, the additional overhead of using Tor is unnecessary when they already use a VPN.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you feel using Tor would be a good thing, then it&amp;rsquo;s best to first connect to your VPN before opening up Tor because it means your VPN won&amp;rsquo;t be able to see what you&amp;rsquo;re doing inside the Tor network (which might be useful in the unlikely scenario where your VPN is compromised).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Equally, if there is a bug in Tor (this has happened), then the VPN will offer that extra layer of protection.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is even an entire OS that is bootable from a USB stick that routes all traffic through Tor, called &lt;a href=&#34;https://tails.boum.org/&#34; target=&#34;_blank&#34;&gt;Tails&lt;/a&gt; (see &lt;a href=&#34;https://www.theregister.co.uk/2019/01/30/tails_3_12/&#34; target=&#34;_blank&#34;&gt;this simple rundown&lt;/a&gt; for a recent update, and &lt;a href=&#34;https://www.expressvpn.com/blog/tails2-review/&#34; target=&#34;_blank&#34;&gt;this older review&lt;/a&gt; for a more general feature run through).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;web-browser-extensions&#34;&gt;Web Browser Extensions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I personally use the &lt;a href=&#34;https://www.mozilla.org/en-GB/firefox/new/&#34; target=&#34;_blank&#34;&gt;Firefox&lt;/a&gt; as it offers me the best of performance and customization. Along with using a VPN I like to utilize some additional &amp;lsquo;extensions&amp;rsquo; (or add-ons as they&amp;rsquo;re referred to by Firefox) to extend the behaviour of my web browser and to help reduce my ability to be tracked.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The below image shows some of the add-ons I utilize:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-addons.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-addons.png&#34; alt=&#34;firefox addons&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The ones of relevance here are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Cookie Quick Manager&lt;/strong&gt;: simple UI for editing/deleting cookies (useful to see what&amp;rsquo;s being set and by whom!).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Privacy Badger&lt;/strong&gt;: blocks invisible third-party trackers.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ExpressVPN&lt;/strong&gt;: allows for doing things like &amp;lsquo;double hops&amp;rsquo;, spoofing my location, blocking WebRTC and enforcing HTTPS.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;NoScript&lt;/strong&gt;: blocks JavaScript and allows me to configure how specific scripts are run and for how long they&amp;rsquo;re trusted.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;uBlock&lt;/strong&gt;: blocks ads, pop ups, and trackers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Old add-ons I used to have installed&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Cookie AutoDelete&lt;/strong&gt;: highly configurable way to delete cookies once you&amp;rsquo;ve finished browsing (whether it be changing domain, or tabs or browser restart).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;DuckDuckGo Privacy Essentials&lt;/strong&gt;: blocks hidden trackers, forces encryption via HTTPS, private search data, tools for grading websites based on their privacy performance.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In the case of &amp;lsquo;DuckDuckGo Privacy Essentials&amp;rsquo; I removed that once I had &amp;lsquo;ExpressVPN&amp;rsquo; and &amp;lsquo;Privacy Badger&amp;rsquo; installed as I needed &amp;lsquo;ExpressVPN&amp;rsquo; any way (and that has &amp;lsquo;HTTPS Everywhere&amp;rsquo; built-in like DDG did), but also &amp;lsquo;Privacy Badger&amp;rsquo; was much a more advanced tracker blocker than DDG was.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of &amp;lsquo;Cookie AutoDelete&amp;rsquo; I removed that once I installed &amp;lsquo;Privacy Badger&amp;rsquo; and &amp;lsquo;NoScript&amp;rsquo; as both those add-ons aided with the same problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a screenshot of what the &amp;lsquo;NoScript&amp;rsquo; add-on looks like:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-noscript-example.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-noscript-example.png&#34; alt=&#34;firefox noscript example&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a screenshot of what the &amp;lsquo;uBlock&amp;rsquo; add-on looks like when visiting &lt;code&gt;google.com&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-ublock-example.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-ublock-example.png&#34; alt=&#34;firefox ublock example&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a screenshot of what the &amp;lsquo;DuckDuckGo Privacy Essentials&amp;rsquo; add-on looks like:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-duckduckgo.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-duckduckgo.png&#34; alt=&#34;firefox duckduckgo&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, each release of Firefox improves the Privacy settings available and so things like content blocking and preventing &amp;lsquo;&lt;a href=&#34;https://blog.mozilla.org/firefox/how-to-block-fingerprinting-with-firefox/&#34; target=&#34;_blank&#34;&gt;browser fingerprinting&lt;/a&gt;&amp;rsquo; is starting to be rolled out more generally for Firefox users:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-security-strict.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-security-strict.png&#34; alt=&#34;firefox security strict&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a screenshot of Firefox&amp;rsquo;s built-in &amp;ldquo;Do Not Track&amp;rdquo; setting (which is definitely worth enabling, even if respecting it is only &lt;em&gt;voluntary&lt;/em&gt;):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-do-not-track.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-do-not-track.png&#34; alt=&#34;firefox do not track&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a screenshot of what Firefox looks like when inspecting a web page that has had content blocked:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-content-blocking.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-content-blocking.png&#34; alt=&#34;firefox content blocking&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But all that said, it&amp;rsquo;s still worth checking what your browser is doing. For example, Firefox enables specific types of data collection which may be worth you disabling:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/firefox-data-collection.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/firefox-data-collection.png&#34; alt=&#34;firefox data collection&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;email&#34;&gt;Email&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Email through free providers such as Google&amp;rsquo;s &lt;a href=&#34;https://gmail.com/&#34; target=&#34;_blank&#34;&gt;Gmail&lt;/a&gt; are definitely NOT private. Google has already admitted to reading their user&amp;rsquo;s emails in order to serve them advertising based on the content of their email.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you are not paying for the service then you&amp;rsquo;re not a &amp;lsquo;customer&amp;rsquo;. You are in fact a &amp;lsquo;target&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An alternative is to use an email provider that encrypts your messages and doesn&amp;rsquo;t have access to their content in any way. A good option (which has a free tier, but obviously you&amp;rsquo;ll use up that free tier pretty quickly) is &lt;a href=&#34;https://proton.me&#34; target=&#34;_blank&#34;&gt;Proton&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;due to how they encrypt your data, if you forget your password and try to reset it, you&amp;rsquo;ll lose &lt;em&gt;all&lt;/em&gt; your email because they don&amp;rsquo;t have a means to decrypt those files unless you provide the relevant password.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Remember, staying &amp;lsquo;anonymous&amp;rsquo; and &amp;lsquo;protecting your privacy&amp;rsquo; are actually different things. The tools I use above will not help to keep my internet actions &lt;em&gt;anonymous&lt;/em&gt;. If you want a good breakdown of what that would take (which is a lot of effort!) then &lt;a href=&#34;https://blog.windscribe.com/how-to-actually-be-anonymous-online-801811b7088d?gi=317e75c4d929&#34; target=&#34;_blank&#34;&gt;read this article&lt;/a&gt; by Windscribe VPN.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Security is hard, and a never ending challenge to get right. But hopefully this post has given you some ideas about the various tools you can use to help you stay anonymous and to protect your privacy.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/anonymity/</guid>
      <link>https://www.integralist.co.uk/posts/anonymity/</link>
      <pubDate>Wed, 04 Sep 2019 00:00:00 +0000</pubDate>
      <title>Staying Anonymous</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Caching is hard. Let&amp;rsquo;s try and understand it a little better.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;some sections are purposefully brief. I&amp;rsquo;m not aiming to be a specification document.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;caching-at-multiple-layers&#34;&gt;Caching at multiple layers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Caching can occur at both a &amp;lsquo;client&amp;rsquo; level and a &amp;lsquo;cache proxy&amp;rsquo; level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following request flow architecture diagram&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/buzzfeed-request-flow-arch.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/buzzfeed-request-flow-arch.png&#34; alt=&#34;buzzfeed request flow arch&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above diagram, the &amp;ldquo;CDN&amp;rdquo; is a &amp;lsquo;caching proxy&amp;rsquo; and so caching can (and of course does) happen there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The box that&amp;rsquo;s labelled &amp;ldquo;proxy&amp;rdquo; in the above diagram &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; a caching proxy, it&amp;rsquo;s just a standard &amp;lsquo;reverse proxy&amp;rsquo; that&amp;rsquo;s figuring out which (of many) &amp;lsquo;origins&amp;rsquo; the request should be proxied onto (meaning: caching does &lt;em&gt;not&lt;/em&gt; happen there).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re able to control caching for both &amp;lsquo;clients&amp;rsquo; and &amp;lsquo;cache proxies&amp;rsquo;, using the following two HTTP response headers:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt;: tells a &amp;lsquo;client&amp;rsquo; (e.g. web browser) how caching should be handled.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control&lt;/code&gt;: tells a &amp;lsquo;proxy&amp;rsquo; (e.g. caching proxy/cdn) how caching should be handled.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In order to cache content efficiently we need to use a combination of the two headers.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;Surrogate-Control&lt;/code&gt; is typically stripped from the response, by a cache proxy, before the client receives it.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#cache-control-directives&#34;&gt;Cache-Control Directives&lt;/a&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#client-requests&#34;&gt;client requests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#no-cache-vs-must-revalidate&#34;&gt;no-cache vs must-revalidate&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#surrogate-control-directives&#34;&gt;Surrogate-Control Directives&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#fastly-cdn&#34;&gt;Fastly CDN&lt;/a&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#default-ttls&#34;&gt;Default TTLs&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#disable-caching&#34;&gt;Disable Caching&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#serving-stale-content&#34;&gt;Serving Stale Content&lt;/a&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#etag-or-last-modified&#34;&gt;ETag or Last-Modified?&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#revalidation-ttl&#34;&gt;Revalidation TTL&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#strong-and-weak-validators&#34;&gt;Strong and Weak Validators&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#cache-headers-example&#34;&gt;Cache Headers Example&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;cache-control-directives&#34;&gt;Cache-Control Directives&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;Cache-Control&lt;/code&gt; cache response header has many directives you can configure, the following are some important ones to understand and will help you make an informed choice as to what values you set if you intend on controlling the caching of your content.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;public&lt;/code&gt;: content can be cached by both client and proxy (implicit default).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;private&lt;/code&gt;: content can be cached by client, but not proxy (as content is &lt;em&gt;unique&lt;/em&gt; to the user).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;max-age&lt;/code&gt;: determines how long (seconds) content is cached, after which requests will reach origin.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;s-maxage&lt;/code&gt;: used by &amp;lsquo;shared cache&amp;rsquo; proxies and is equivalent to &lt;code&gt;Surrogate-Control: max-age=&amp;lt;...&amp;gt;&lt;/code&gt; (except not stripped).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;must-revalidate&lt;/code&gt;: cached content can be served if TTL hasn&amp;rsquo;t expired, but do not serve &amp;lsquo;stale&amp;rsquo; content under &lt;em&gt;any&lt;/em&gt; circumstance.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;no-cache&lt;/code&gt;: cached content must revalidate on all requests (i.e. serve stale is fine, but only after consulting origin).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;no-store&lt;/code&gt;: prevents client or proxies from caching the content.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;no-transform&lt;/code&gt;: proxies aren&amp;rsquo;t allowed to modify content (e.g. don&amp;rsquo;t send compressed content if origin didn&amp;rsquo;t).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;References: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control&#34; target=&#34;_blank&#34;&gt;MDN: &lt;code&gt;Cache-Control&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html&#34; target=&#34;_blank&#34;&gt;W3C Specification&lt;/a&gt; (see also: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching&#34; target=&#34;_blank&#34;&gt;MDN: Caching&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;client-requests&#34;&gt;client requests&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One typically unmentioned feature of the &lt;code&gt;Cache-Control&lt;/code&gt; HTTP header is that it can also be utilised at the client level for indicating to a cache what it will and wont accept.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is an interesting perspective on caching that we rarely see.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of Fastly CDN, they will ignore the &lt;code&gt;Cache-Control&lt;/code&gt; header and its directives when provided as part of the client request.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reference: &lt;a href=&#34;https://tools.ietf.org/html/rfc7234#page-22&#34; target=&#34;_blank&#34;&gt;RFC&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;no-cache-vs-must-revalidate&#34;&gt;no-cache vs must-revalidate&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A lot of the &lt;code&gt;Cache-Control&lt;/code&gt; directives have subtle overlapping responsibilities, and &lt;code&gt;no-cache&lt;/code&gt;/&lt;code&gt;must-revalidate&lt;/code&gt; is one of the more confusing ones, so I&amp;rsquo;d like to take a moment to add some extra clarity&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With &lt;code&gt;must-revalidate&lt;/code&gt; it&amp;rsquo;s suggesting that cached content must revalidate and not serve stale after the cached content&amp;rsquo;s &lt;code&gt;max-age&lt;/code&gt; TTL has expired.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is effectively saying &amp;ldquo;we have some content cached and its TTL is still valid so we&amp;rsquo;ll return that to you&amp;rdquo;, but the moment the &lt;code&gt;max-age&lt;/code&gt; TTL expires it then changes to &amp;ldquo;sorry, we &lt;em&gt;had&lt;/em&gt; cached content but it&amp;rsquo;s now stale and we&amp;rsquo;re not allowed to use it. we&amp;rsquo;ll go to the origin and grab fresh content for you.&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unlike &lt;code&gt;no-cache&lt;/code&gt; which is effectively saying &amp;ldquo;we have cached content, but before we release it to you we&amp;rsquo;re going to check with the origin that there isn&amp;rsquo;t a fresher version first&amp;rdquo;. It&amp;rsquo;s a way of enforcing a &lt;em&gt;rigid&lt;/em&gt; &amp;lsquo;freshness&amp;rsquo; plan.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whenever using these (and other similar) directives, you need give consideration to what else needs to be in place to make them function efficiently. Specifically you need to be sure your origins are actually capable of handling revalidation (see &amp;lsquo;&lt;a href=&#34;#serving-stale-content&#34;&gt;Serving Stale Content&lt;/a&gt;&amp;rsquo; for more details), otherwise the behaviours might not work as intended or perform as well as you think they will.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;surrogate-control-directives&#34;&gt;Surrogate-Control Directives&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For the &lt;code&gt;Surrogate-Control&lt;/code&gt; cache response header you&amp;rsquo;ll mostly utilize the &lt;code&gt;max-age&lt;/code&gt; directive along with the &amp;lsquo;&lt;a href=&#34;https://httpwg.org/specs/rfc5861.html&#34; target=&#34;_blank&#34;&gt;extensions&lt;/a&gt;&amp;rsquo; for serving stale content (e.g. &lt;code&gt;stale-while-revalidate&lt;/code&gt; and &lt;code&gt;stale-if-error&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are some other directives defined in the &lt;a href=&#34;https://www.w3.org/TR/edge-arch/&#34; target=&#34;_blank&#34;&gt;W3C Specification&lt;/a&gt;, but it&amp;rsquo;s unclear how well those are supported by our primary CDN provider (Fastly) and so it&amp;rsquo;s best to avoid them unless you fully understand why you are setting them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-cdn&#34;&gt;Fastly CDN&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Fastly &lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial&#34; target=&#34;_blank&#34;&gt;has some rules&lt;/a&gt; about the various caching response headers it respects and in what order this behaviour is applied. The following is a summary of these rules:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control&lt;/code&gt; determines proxy caching behaviour (takes priority over &lt;code&gt;Cache-Control&lt;/code&gt;) †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines client caching behaviour.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines both client/proxy caching behaviour if no &lt;code&gt;Surrogate-Control&lt;/code&gt; †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines both client/proxy caching behaviour if it includes both &lt;code&gt;max-age&lt;/code&gt; and &lt;code&gt;s-maxage&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt; determines both client/proxy caching behaviour if no &lt;code&gt;Cache-Control&lt;/code&gt; or &lt;code&gt;Surrogate-Control&lt;/code&gt; headers.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt; ignored if &lt;code&gt;Cache-Control&lt;/code&gt; is also set (recommended to avoid &lt;code&gt;Expires&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Pragma&lt;/code&gt; is a legacy cache header only recommended if you need to support older HTTP/1.0 protocol.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† &lt;em&gt;except&lt;/em&gt; when &lt;code&gt;Cache-Control&lt;/code&gt; contains &lt;code&gt;private&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth reiterating a segment of the above priority list which is that &lt;code&gt;Cache-Control&lt;/code&gt; &lt;em&gt;can&lt;/em&gt; include serving stale directives such as &lt;code&gt;stale-while-revalidate&lt;/code&gt; and &lt;code&gt;stale-if-error&lt;/code&gt;, but they are typically utilized with &lt;code&gt;Surrogate-Control&lt;/code&gt; more than they are with &lt;code&gt;Cache-Control&lt;/code&gt;. If Fastly receives no &lt;code&gt;Surrogate-Control&lt;/code&gt; but it does get &lt;code&gt;Cache-Control&lt;/code&gt; with those directives it &lt;em&gt;will&lt;/em&gt; presume those are defined for its benefit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Client devices (e.g. web browsers) can respect those stale directives, but it&amp;rsquo;s not very well supported currently (see &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility&#34; target=&#34;_blank&#34;&gt;MDN compatibility table&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in learning more about Fastly (inc. Varnish and VCL), then &lt;a href=&#34;/posts/fastly-varnish&#34;&gt;read my blog post&lt;/a&gt; on the topic.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;default-ttls&#34;&gt;Default TTLs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The CDN (Fastly) &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/controlling-caching&#34; target=&#34;_blank&#34;&gt;has some rules&lt;/a&gt; about how long it will cache content for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a (oversimplified †) summary of these rules.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If your origin doesn&amp;rsquo;t set a cache response header, then cache content TTL will be 1hr.&lt;/li&gt;&#xA;&lt;li&gt;1hr TTL is set by &lt;a href=&#34;https://docs.fastly.com/vcl/custom-vcl/creating-custom-vcl/&#34; target=&#34;_blank&#34;&gt;Fastly&amp;rsquo;s VCL boilerplate&lt;/a&gt; (applied by default).&lt;/li&gt;&#xA;&lt;li&gt;1hr TTL can be overridden by your own custom VCL.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† Fastly has many factors it takes into account when deciding if an object stays in its cache (see: &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/serving-stale-content#why-serving-stale-content-may-not-work-as-expected&#34; target=&#34;_blank&#34;&gt;LRU&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;disable-caching&#34;&gt;Disable Caching&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Depending on your requirements, when trying to disable caching it can be confusing to know which cache control directives to utilize due to the various permutations. Below is a Fastly recommended list of directives your origin can use for handling three common scenarios.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Disable Client Caching (&lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial#applying-different-cache-rules-for-fastly-and-browsers&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;): &lt;code&gt;Cache-Control: no-store, must-revalidate&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Disable Proxy Caching (&lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial#do-not-cache&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;): &lt;code&gt;Cache-Control: private&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Disable ALL Caching (&lt;a href=&#34;https://docs.fastly.com/guides/debugging/temporarily-disabling-caching&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;):&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control: no-cache, no-store, private, must-revalidate, max-age=0, max-stale=0, post-check=0, pre-check=0&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Pragma: no-cache&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires: 0&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;regarding the disabling of caching at the client level, I reached out to Fastly because of their suggested use of &lt;code&gt;must-revalidate&lt;/code&gt; &lt;em&gt;with&lt;/em&gt; &lt;code&gt;no-store&lt;/code&gt; (which doesn&amp;rsquo;t make sense). They have since consulted with their resident RFC expert who confirmed this was redundant, and so expect their documentation to be updated to just &lt;code&gt;no-store&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also worth mentioning that Fastly&amp;rsquo;s use of &lt;code&gt;post-check&lt;/code&gt; and &lt;code&gt;pre-check&lt;/code&gt; is &lt;em&gt;also&lt;/em&gt; redundant as per &lt;a href=&#34;https://blogs.msdn.microsoft.com/ie/2006/06/01/a-caching-issue-in-ie7-beta-2/&#34; target=&#34;_blank&#34;&gt;this old Microsoft article&lt;/a&gt; that states setting them to zero does not actually &amp;lsquo;do anything&amp;rsquo;!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;serving-stale-content&#34;&gt;Serving Stale Content&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As you saw at the beginning of this post, we have a &amp;lsquo;reverse proxy&amp;rsquo; that&amp;rsquo;s placed in front of our origin servers. This proxy will configure (as a default) cache settings that will result in stale versions of our origin&amp;rsquo;s cached content being served when the &lt;code&gt;max-age&lt;/code&gt; TTL for that content has expired.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are two distinct types of serving stale logic:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;stale-while-revalidate&lt;/code&gt;: serve stale content while asynchronously checking for fresh content.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;stale-if-error&lt;/code&gt;: serve stale content if request to origin fails.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A key part of the &lt;code&gt;stale-while-revalidate&lt;/code&gt; flow is for the origin to indicate when a particular resource has been &amp;lsquo;refreshed&amp;rsquo; (i.e. a newer version is available). This is achieved by the origin providing either an &lt;code&gt;ETag&lt;/code&gt; (entity tag) or a &lt;code&gt;Last-Modified&lt;/code&gt; response header.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ETag&lt;/code&gt; and &lt;code&gt;Last-Modified&lt;/code&gt; response headers (sent from the origin) are used as values in a &amp;lsquo;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests&#34; target=&#34;_blank&#34;&gt;conditional request&lt;/a&gt;&amp;rsquo; made by the cache (client or proxy cache) to determine if the origin should send back either a full response or a smaller &lt;code&gt;304 Not Modified&lt;/code&gt; if the revalidated content hasn&amp;rsquo;t changed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The benefit of a conditional request is that we&amp;rsquo;re able to reduce bandwidth whenever a &lt;code&gt;304 Not Modified&lt;/code&gt; is returned from the origin, because it will be sent with an empty response body (where as, of course, &lt;code&gt;200 OK&lt;/code&gt; will include the full response body).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Conditional_headers&#34; target=&#34;_blank&#34;&gt;conditional headers&lt;/a&gt;, but the following are the most common when dealing with &lt;code&gt;ETag&lt;/code&gt;/&lt;code&gt;Last-Modified&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ETag: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;If-None-Match&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Last-Modified: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;If-Modified-Since&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Reference: &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Use_cases&#34; target=&#34;_blank&#34;&gt;sequence diagrams demonstrating the various request flows&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If neither &lt;code&gt;ETag&lt;/code&gt; nor &lt;code&gt;Last-Modified&lt;/code&gt; is sent by the origin, then the cache will not be able to update the cache object. This means the object&amp;rsquo;s TTL (i.e. &lt;code&gt;max-age&lt;/code&gt;) will still be expired, and other properties of the cache object will also not be updated, such as its &amp;lsquo;age&amp;rsquo; (reset it back to zero once the content is refreshed), nor its &amp;lsquo;grace&amp;rsquo; period (how long it will be able to serve that content stale for).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;etag-or-last-modified&#34;&gt;ETag or Last-Modified?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The official &lt;a href=&#34;https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4&#34; target=&#34;_blank&#34;&gt;W3C specification&lt;/a&gt; provides &amp;lsquo;rules&amp;rsquo; for when to use ETag vs Last-Modified. In summary&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;the preferred behavior for an HTTP/1.1 origin server is to send &lt;strong&gt;both&lt;/strong&gt; a strong entity tag and a Last-Modified value.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;A good additional reference is MDN&amp;rsquo;s article on &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching#Cache_validation&#34; target=&#34;_blank&#34;&gt;Cache Validation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;revalidation-ttl&#34;&gt;Revalidation TTL&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One aspect of serving stale content that normally confuses people is how to determine the TTL for &lt;code&gt;stale-while-revalidate&lt;/code&gt;. It would seem that determining a TTL for &lt;code&gt;stale-if-error&lt;/code&gt; is fairly straight forward, in that you&amp;rsquo;ll just pick an arbitrarily long time period to serve stale, while the &lt;code&gt;stale-while-revalidate&lt;/code&gt; directive isn&amp;rsquo;t as simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following diagram which highlights a typical request flow when using (for example) an &lt;code&gt;ETag&lt;/code&gt; to handle the revalidation step:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this diagram presumes the use of a CDN like Fastly which has specific behaviours, such as &amp;lsquo;request collapsing&amp;rsquo; built-in.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/http-conditional-requests.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/http-conditional-requests.png&#34; alt=&#34;http conditional requests&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this request flow we can see that although we&amp;rsquo;re successfully serving stale content when a cached object&amp;rsquo;s TTL has expired, this is still potentially going to result in multiple requests to the origin (rather than acting as a cache HIT) if we have an influx of requests for the same resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now with that said, the ability to reach the origin (if we&amp;rsquo;re using Fastly at least, other CDN providers may differ) is only going to be on a datacenter by datacenter basis. The reason being, each &lt;a href=&#34;/posts/fastly-varnish/#clustering&#34;&gt;cache node&lt;/a&gt; will perform &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/request-collapsing&#34; target=&#34;_blank&#34;&gt;request collapsing&lt;/a&gt; which will mitigate the damage of having to allow a request through to your origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this in mind, having a large &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL might not necessarily be a good idea because ultimately for that time period, if there is no updated version of the content, new client requests are going to be able to reach the origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Yes, it&amp;rsquo;s not going to be millions of requests (even if you&amp;rsquo;re a globally distributed brand), and Yes, having an empty response sent back from origin with the &lt;code&gt;304 Not Modified&lt;/code&gt; is better as far as bandwidth consumption is concerned, but the origin still has to spend time and resources constructing the response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So depending on your origin and potentially the costs related to these types of requests it might be better to have a shorter &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL so that it would expire more quickly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This would then mean the request would go back to the origin &lt;em&gt;sooner&lt;/em&gt;, in order to get a full response back to be re-cached, which would then result in future client requests actually getting a cache HIT and saving the origin from having to handle that extra unnecessary load.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the &amp;lsquo;flip side&amp;rsquo;, I think the &lt;em&gt;actual&lt;/em&gt; question needed to be asked is: &amp;ldquo;how important is it that you get fresh content as quickly as possible&amp;rdquo;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The answer to &lt;em&gt;that&lt;/em&gt; will firstly depend on whether we were using a CDN where purging content dynamically was not possible (specifically whenever fresh content was published by an origin). Fastly enables this dynamic purging by providing support for setting a &lt;code&gt;Surrogate-Key&lt;/code&gt; HTTP response header.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if we &lt;em&gt;were&lt;/em&gt; in that situation where we couldn&amp;rsquo;t dynamically purge our CDN cache, and the freshness of our content was important then I would imagine we would set a longer &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL in order to force the caching proxy to attempt to revalidate &lt;em&gt;more often&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Otherwise, again if we were in that situation where we couldn&amp;rsquo;t dynamically purge our CDN cache and we had ended up setting a &lt;em&gt;short&lt;/em&gt; &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL, then that would mean we&amp;rsquo;d go back to origin and get a new &lt;code&gt;max-age&lt;/code&gt; TTL set (which could be set to a very long value) and so we could end up with users getting a cache HIT for content which for all extensive purposes could very well be stale anyway but you would lose the opportunity to try and acquire fresh content via revalidation now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re using a CDN such as Fastly, you can utilize &lt;code&gt;Surrogate-Key&lt;/code&gt; to purge your content dynamically whenever fresher versions have been published. Meaning, you could have a short revalidation TTL and if there was no fresh content within that time period you wouldn&amp;rsquo;t actually have to worry about going to origin and getting the same content back but now with a long &lt;code&gt;max-age&lt;/code&gt; TTL, because you know you could dynamically trigger a cache MISS whenever your fresh content was published anyway.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Open Question: do &lt;em&gt;you&lt;/em&gt; think &lt;code&gt;stale-while-revalidate&lt;/code&gt; should contain a long or short TTL (and why)?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;strong-and-weak-validators&#34;&gt;Strong and Weak Validators&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As far as the actual &lt;em&gt;setting&lt;/em&gt; of an &lt;code&gt;ETag&lt;/code&gt; is concerned, this isn&amp;rsquo;t necessarily as straight forward as you might first imagine. For example, a typical approach is to use a hash function to generate a digest of the response body to verify the content has changed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Of course there is the potential for the hash function to not be robust enough to avoid hash conflicts, but additionally there is a concept referred to as &amp;ldquo;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Validators&#34; target=&#34;_blank&#34;&gt;validation&lt;/a&gt;&amp;rdquo; which needs to be considered (e.g. should the &lt;code&gt;ETag&lt;/code&gt; be marked as being a &amp;ldquo;strong&amp;rdquo; validator or a &amp;ldquo;weak&amp;rdquo; validator).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These are things that you&amp;rsquo;ll need to consider when generating an &lt;code&gt;ETag&lt;/code&gt; for a resource, and it&amp;rsquo;s recommended you read documentation on &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#Strong_validation&#34; target=&#34;_blank&#34;&gt;what constitutes a &amp;ldquo;strong&amp;rdquo; or &amp;ldquo;weak&amp;rdquo; validator&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s important to realize that generating an &lt;code&gt;ETag&lt;/code&gt; and figuring out the &lt;code&gt;Last-Modified&lt;/code&gt; date of a resource is outside the responsibility of a proxy, hence the proxy sat in front of our origins doesn&amp;rsquo;t set these headers even when they aren&amp;rsquo;t set by the origin.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In essence a strong ETag indicates that the resource&amp;rsquo;s content is the same with regards to both the response body and the response headers, whereas a weak ETag indicates that the two representations are semantically equivalent. It compares only the response body. Weak ETags are prefixed with &lt;code&gt;W\&lt;/code&gt; and thus can easily be distinguished between weak and strong.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;cache-headers-example&#34;&gt;Cache Headers Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s wrap up by considering a real-world example of cache headers and what they look like, and why.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The request flow architecture that I have at work takes the form of:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Client &amp;gt; CDN &amp;gt; Load Balancer(LB) &amp;gt; Proxy &amp;gt; LB &amp;gt; Proxy &amp;gt; LB &amp;gt; Origin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are reasons for the multiple proxy layers in front of our origin servers, but I&amp;rsquo;m not going to dig into that here.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The proxy nearest the front of that list is acting as a gateway of sorts, and so if our origins fail to set any caching instructions, that proxy will add some defaults on their behalf.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is all documented as service contracts, and so these origins are choosing to opt into those defaults, but they have full control over how their content is cached if they so choose to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This proxy layer will by default tell the client to &lt;em&gt;not&lt;/em&gt; cache your content, while indicating to any &amp;lsquo;caching proxies&amp;rsquo; (e.g. Fastly CDN) that they &lt;em&gt;should&lt;/em&gt; cache your content:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control: no-store&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control: max-age=86400, stale-while-revalidate=60, stale-if-error=31536000&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;values are in seconds, so &lt;code&gt;86400&lt;/code&gt; = 1 day, &lt;code&gt;60&lt;/code&gt; = 1 minute, &lt;code&gt;31536000&lt;/code&gt; = 1 year.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason for choosing to only cache content at the CDN rather than the client is because we have very granular control over our CDN cached content (thanks to our CDN provider, &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt;) and so its preferable, for our situation, to have complete control over the caching of our content rather than let a client&amp;rsquo;s browser determine what happens.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if we &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; do this and we allowed the client to cache our content in their own private caches, then it would mean if we had a request from our legal department to take down a piece of content, we wouldn&amp;rsquo;t be able to remove it from the client&amp;rsquo;s cache as that&amp;rsquo;s outside of our control.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Things can get a bit murky if there are proxies placed &lt;em&gt;in front&lt;/em&gt; of our CDN (e.g. ISP proxies or maybe client is inside a local corporate network that runs caching proxies), but we set &lt;code&gt;no-store&lt;/code&gt; which &lt;em&gt;should&lt;/em&gt; tell clients/proxies to not cache. The reason this works with Fastly is because it doesn&amp;rsquo;t respect &lt;code&gt;no-store&lt;/code&gt; (it sees that as a client cache directive), it instead respects &lt;code&gt;private&lt;/code&gt; (which is more appropriate), and so that&amp;rsquo;s another way of us hopefully catching any unknown proxies in front of our CDN.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All of this leads us to the fact that when we purge our cache, we feel confident that we&amp;rsquo;re capable of successfully purging it from the internet as a whole.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yes, caching &lt;em&gt;is&lt;/em&gt; hard but it&amp;rsquo;s also not rocket science either. Take some time to read over the &lt;code&gt;Cache-Control&lt;/code&gt; directives. Try to get comfortable with them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s our responsibility as engineers building HTTP services to understand the platform we&amp;rsquo;re building services upon.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;❤️&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/http-caching-guide/</guid>
      <link>https://www.integralist.co.uk/posts/http-caching-guide/</link>
      <pubDate>Tue, 06 Aug 2019 00:00:00 +0000</pubDate>
      <title>HTTP Caching Guide</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m an engineer with a &lt;em&gt;new&lt;/em&gt; laptop, which requires setting up with various&#xA;development tools and configuration. This post is my attempt to capture and&#xA;document my process for getting a new dev environment set-up.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I used to try and automate a lot of this with bash scripts, but realised over&#xA;time that things go out of date quite quickly (e.g. OS configurations can change&#xA;substantially, as well as my preferred ways of working).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I also find that if an error occurs with an automated script (unless you&amp;rsquo;ve&#xA;coded things defensively enough) you can end up with your machine in a weirdly&#xA;broken state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Given a straight forward set of instructions, doing things &lt;em&gt;manually&lt;/em&gt; doesn&amp;rsquo;t&#xA;take long at all, and you can modify things at that point in time without just&#xA;blindly installing various things you no longer need.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;defaults&#34;&gt;Defaults&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s good to begin by surveying your current system and understanding what you&#xA;have already installed. For me this looked something like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;OS: macOS Mojave (&lt;code&gt;10.14.4&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Curl: &lt;code&gt;/usr/bin/curl&lt;/code&gt; (&lt;code&gt;7.54.0&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Bash: &lt;code&gt;/bin/bash&lt;/code&gt; (&lt;code&gt;3.2.57&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Python: &lt;code&gt;/usr/bin/python&lt;/code&gt; (&lt;code&gt;2.7.10&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Ruby: &lt;code&gt;/usr/bin/ruby&lt;/code&gt; (&lt;code&gt;2.3.7p456&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Git: &lt;code&gt;/usr/bin/git&lt;/code&gt; (&lt;code&gt;2.20.1&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;$PATH: &lt;code&gt;/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s worth me noting additionally here is that I primarily use two programming&#xA;languages: Go and Python. The reason I mention this is because Python has an&#xA;interesting history with the name of its binaries.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The binary name &lt;code&gt;python&lt;/code&gt; generally refers to Python version &lt;code&gt;2.x&lt;/code&gt;. Where as&#xA;Python &lt;code&gt;3.x&lt;/code&gt; has traditionally been named &lt;code&gt;python3&lt;/code&gt; to help distinguish the two.&#xA;So looking above we can see &lt;code&gt;which python&lt;/code&gt; reveals the location as&#xA;&lt;code&gt;/usr/bin/python&lt;/code&gt; and without checking the version (e.g. &lt;code&gt;python --version&lt;/code&gt;) I&#xA;was fairly certain it would be a &lt;code&gt;2.x&lt;/code&gt; version (based on the naming history).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This has been the generally accepted rule for a while, &lt;em&gt;except!&lt;/em&gt; when dealing&#xA;with tools that handle virtual environments.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;a href=&#34;https://pipenv.readthedocs.io/&#34; target=&#34;_blank&#34;&gt;pipenv&lt;/a&gt; is a tool that helps you&#xA;to manage not only different Python versions but also the dependencies installed&#xA;for different projects (referred to as virtual environments). A tool like pipenv&#xA;will proxy a command such as &lt;code&gt;python&lt;/code&gt; through a shim script (e.g.&#xA;&lt;code&gt;/Users/integralist/.pyenv/shims/python&lt;/code&gt;) and that shim script will then&#xA;determine which Python interpreter/binary to execute.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A shim script typically identifies the virtual environment you&amp;rsquo;re working under&#xA;and will then figure out the most appropriate Python interpreter to invoke. So&#xA;within that virtual env if you call &lt;code&gt;python&lt;/code&gt;, then you may not necessarily get&#xA;the Python2 interpreter, as your virtual env might be configured such that the&#xA;expectation is to proxy your invocation to a Python3 interpreter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why, when setting up a new laptop, getting a good development&#xA;environment setup is essential because it can get quite confusing untangling a&#xA;mess of default Python&amp;rsquo;s vs &lt;code&gt;brew install ...&lt;/code&gt; versions of Python 3 and then&#xA;subsequently using multiple environment tools like &lt;code&gt;pipenv&lt;/code&gt; which confuse things&#xA;further by hiding the actual versions behind the generically named &lt;code&gt;python&lt;/code&gt;&#xA;command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The situation reminds me a lot of &lt;a href=&#34;https://xkcd.com/1987/&#34; target=&#34;_blank&#34;&gt;XKCD&amp;rsquo;s classic comic&#xA;strip&lt;/a&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/python_env.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/python_env.png&#34; alt=&#34;python env&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;package-manager&#34;&gt;Package Manager&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s begin our journey by first installing a &amp;lsquo;package manager&amp;rsquo;. This software&#xA;will enable us to search and install various pieces of software. The macOS&#xA;provides its own GUI implementation referred to as the &amp;lsquo;App Store&amp;rsquo;, but it&amp;rsquo;s&#xA;heavily moderated by Apple and an app can only be found there if it abides by&#xA;Apple&amp;rsquo;s own set of rules and criteria for what they consider to be &amp;lsquo;safe&amp;rsquo;&#xA;software.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are many apps that aren&amp;rsquo;t available in the App Store because Apple&#xA;can be a bit anti-competition (see &lt;a href=&#34;https://timetoplayfair.com&#34; target=&#34;_blank&#34;&gt;Spotify&amp;rsquo;s &amp;ldquo;time to play fair&amp;rdquo;&#xA;campaign&lt;/a&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So we have to download our own package manager, and the defacto standard for&#xA;macOS is a program called &lt;a href=&#34;https://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt; (which is a terminal&#xA;based tool, so no GUI). In fact, I&amp;rsquo;m not actually sure what &lt;em&gt;alternatives&lt;/em&gt; to&#xA;Homebrew exist (other than &lt;a href=&#34;https://www.macports.org&#34; target=&#34;_blank&#34;&gt;MacPorts&lt;/a&gt;, which if you&#xA;want to understand the differences between it and Homebrew then &lt;a href=&#34;https://saagarjha.com/blog/2019/04/26/thoughts-on-macos-package-managers/&#34; target=&#34;_blank&#34;&gt;read&#xA;this&lt;/a&gt;)?&#xA;On Linux you have tools such as &lt;code&gt;yum&lt;/code&gt; or &lt;code&gt;apt&lt;/code&gt; but for macOS you either use the&#xA;built-in App Store or find your own alternative (so in this case, we&amp;rsquo;ll use&#xA;Homebrew).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To install Homebrew, execute the following command in your terminal:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/usr/bin/ruby -e &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;notice that installation command uses the default installation of Ruby&#xA;which Homebrew presumes is available (and for the most part is a safe&#xA;presumption to make as Ruby as been provided by macOS for the longest time).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you need to update Homebrew you can execute a &lt;code&gt;brew update&lt;/code&gt; command, but the&#xA;installation will install the latest version any way, so that won&amp;rsquo;t be&#xA;necessary.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;essential-packages&#34;&gt;Essential Packages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so I start with what I refer to as a &amp;lsquo;essential packages&amp;rsquo;, and specifically&#xA;these are packages that do not require any configuration on my part. Meaning, I&#xA;can install them and consider the job done, where as with other packages I&#xA;install I&amp;rsquo;ll have to make some additional tweaks to (which we&amp;rsquo;ll see as we move&#xA;on past the &amp;lsquo;essential&amp;rsquo; segments of this post).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To install a package via Homebrew, execute the following command in your&#xA;terminal:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install &amp;lt;package_name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a list of the packages I&amp;rsquo;ll install:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ag&lt;/code&gt;: a &lt;code&gt;grep&lt;/code&gt; like tool (aka. the_silver_searcher)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gnu-sed&lt;/code&gt;: it&amp;rsquo;s the gnu version of &lt;code&gt;sed&lt;/code&gt; (&lt;code&gt;gsed&lt;/code&gt;) used for filtering/transforming text&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;jq&lt;/code&gt;: tool for parsing/inspecting json output&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;docker&lt;/code&gt;: useful for running containerized programs&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hugo&lt;/code&gt;: static site generator (used to make this website)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;node&lt;/code&gt;: server-side js programming language (used to compile a static search feature for my website)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pwgen&lt;/code&gt;: generates random passwords&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;reattach-to-user-namespace&lt;/code&gt;: used by tmux for clipboard storage&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;shellcheck&lt;/code&gt;: bash linter&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;transmission&lt;/code&gt;: torrent client † (alt. &lt;code&gt;npm install -g t-get&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tree&lt;/code&gt;: displays directory heirarchy structures as a tree&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;watch&lt;/code&gt;: executes given command every N seconds&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† see &lt;a href=&#34;https://cli-ck.io/transmission-cli-user-guide/&#34; target=&#34;_blank&#34;&gt;transmission user guide&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a handy one-liner:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install ag gnu-sed jq docker hugo node pwgen reattach-to-user-namespace shellcheck tree watch&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;essential-apps&#34;&gt;Essential Apps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Homebrew now allows you to also install GUI applications, not just command line&#xA;tools, but to do this you&amp;rsquo;ll need to configure Homebrew to use &lt;code&gt;Cask&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew tap homebrew/cask&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once that&amp;rsquo;s done you can install an app via Homebrew using the command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew cask install &amp;lt;app_name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a list of the apps I&amp;rsquo;ll install:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;alfred&lt;/code&gt;: like Apple&amp;rsquo;s Spotlight search, but better&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;caffeine&lt;/code&gt;: stops the Mac from going to sleep&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;dash&lt;/code&gt;: offline documentation&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;docker&lt;/code&gt;: this is the counter-part to the &amp;lsquo;package&amp;rsquo; installed earlier †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;google-backup-and-sync&lt;/code&gt;: syncs files between computer and Google Drive&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;google-chrome&lt;/code&gt;: web browser&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;lepton&lt;/code&gt;: GitHub Gist UI&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;slack&lt;/code&gt;: communication tool&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;spotify&lt;/code&gt;: music streaming service&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vlc&lt;/code&gt;: video player with support of lots of codecs&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† if you installed the docker &amp;lsquo;package&amp;rsquo;, then you &lt;em&gt;need&lt;/em&gt; the docker &amp;lsquo;app&amp;rsquo; as&#xA;well for it to work. You can&amp;rsquo;t have one without the other (this is because the&#xA;app sets up the interface for macOS to interact with the underlying docker&#xA;client/server implementation).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a handy one-liner:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew cask install alfred caffeine dash docker google-backup-and-sync google-chrome lepton slack spotify vlc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://kapeli.com/dash&#34; target=&#34;_blank&#34;&gt;Dash&lt;/a&gt; app will ask you what documentation you&#xA;would like to download so it&amp;rsquo;s available offline. I use the following docsets (I&#xA;used to have &lt;em&gt;lots&lt;/em&gt; more but realised I never really used them, so this is my&#xA;&amp;lsquo;essential&amp;rsquo; docs list):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;boto3&lt;/li&gt;&#xA;&lt;li&gt;Go&lt;/li&gt;&#xA;&lt;li&gt;HTTP Header Fields&lt;/li&gt;&#xA;&lt;li&gt;HTTP Status Codes&lt;/li&gt;&#xA;&lt;li&gt;NGINX&lt;/li&gt;&#xA;&lt;li&gt;Python2&lt;/li&gt;&#xA;&lt;li&gt;Python3&lt;/li&gt;&#xA;&lt;li&gt;Regular Expressions&lt;/li&gt;&#xA;&lt;li&gt;tmux&lt;/li&gt;&#xA;&lt;li&gt;Tornado&lt;/li&gt;&#xA;&lt;li&gt;vim&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A couple of apps probably worth mentioning are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/dwarvesf/hidden&#34; target=&#34;_blank&#34;&gt;https://github.com/dwarvesf/hidden&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/leits/MeetingBar&#34; target=&#34;_blank&#34;&gt;https://github.com/leits/MeetingBar&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;curl&#34;&gt;Curl&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I like to use a more modern version of &lt;code&gt;curl&lt;/code&gt; (e.g. supports HTTP/2, and other features):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install curl&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But in order to use this version of curl you&amp;rsquo;ll need to modify your &lt;code&gt;$PATH&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export PATH=&amp;quot;/usr/local/opt/curl/bin:$PATH&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;git&#34;&gt;Git&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Similarly to curl, I like to have the most recent version of &lt;code&gt;git&lt;/code&gt; installed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once that&amp;rsquo;s installed I configure it like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -LSso ~/.git-prompt.sh https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh&#xA;curl -LSso ~/.gitignore-global https://raw.githubusercontent.com/Integralist/dotfiles/master/.gitignore-global&#xA;curl -LSso ~/.gitconfig https://raw.githubusercontent.com/Integralist/dotfiles/master/.gitconfig&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s always worth checking &lt;code&gt;~/.gitignore-global&lt;/code&gt; is up to date (i.e. not&#xA;referencing file types I no longer work with).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;shell&#34;&gt;Shell&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To install and configure latest version of the Bash shell, execute the following&#xA;commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install bash&#xA;echo /usr/local/bin/bash | sudo tee -a /etc/shells&#xA;chsh -s /usr/local/bin/bash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Also make sure to install auto-complete for bash:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install bash-completion&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, we&amp;rsquo;ll configure Bash like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -LSso ~/.bash-preexec.sh https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh&#xA;curl -LSso ~/.bashrc https://raw.githubusercontent.com/Integralist/dotfiles/master/.bashrc&#xA;curl -LSso ~/.bash_profile https://raw.githubusercontent.com/Integralist/dotfiles/master/.bash_profile&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;~/.bashrc&lt;/code&gt; references &lt;code&gt;~/.fzf.bash&lt;/code&gt; which is needed, and comes from&#xA;installing the FZF vim plugin (which we&amp;rsquo;ll sort out shortly).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;terminal&#34;&gt;Terminal&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To install my custom terminal theme:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -LSso /tmp/Integralist.terminal \&#xA;https://raw.githubusercontent.com/Integralist/mac-os-terminal-theme-integralist/master/Integralist.terminal&#xA;open /tmp/Integralist.terminal&#xA;rm /tmp/Integralist.terminal&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t forget to change the terminal font to menlo (if not already set)&#xA;and also set &lt;code&gt;Integralist&lt;/code&gt; theme as your default. I used to do this via&#xA;&lt;code&gt;defaults write com.apple.Terminal &amp;quot;Default Window Settings&amp;quot; Integralist&lt;/code&gt; and&#xA;&lt;code&gt;defaults write com.apple.Terminal &amp;quot;Startup Window Settings&amp;quot; Integralist&lt;/code&gt; but&#xA;those have changed now in the latest macOS (see &lt;code&gt;defaults read&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;update-2020-09-08&#34;&gt;UPDATE 2020.09.08&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve reverted to using the &amp;ldquo;Basic&amp;rdquo; theme provided by macOS, and just modifying&#xA;the font to be &amp;ldquo;Menlo Regular 16 pt.&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;github&#34;&gt;GitHub&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now set-up a new SSH key for GitHub access:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir ~/.ssh&#xA;cd ~/.ssh &amp;amp;&amp;amp; ssh-keygen -t rsa -b 4096 -C &#39;foobar@example.com&#39;&#xA;eval &amp;quot;$(ssh-agent -s)&amp;quot;&#xA;ssh-add -K ~/.ssh/github_rsa&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t forget to &lt;code&gt;pbcopy &amp;lt; ~/.ssh/github_rsa.pub&lt;/code&gt; and paste your public key into&#xA;the GitHub UI. Once that&amp;rsquo;s done you can execute the following command to test&#xA;your SSH key is set-up correctly and working:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ssh -T git@github.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is a slight catch-22 here which is if your password for GitHub is&#xA;in your Password Store (see next section), then that makes things trickier.&#xA;For me I also have a copy of the encrypted store on my phone and so I can&#xA;utilise that to access the password. But failing that, you can just &amp;lsquo;reset&#xA;your password&amp;rsquo; in GitHub UI&amp;rsquo;s and follow the email instructions to gain access&#xA;and thus login and add your new SSH key.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;password-store&#34;&gt;Password Store&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I use the open-source &lt;a href=&#34;https://www.passwordstore.org&#34; target=&#34;_blank&#34;&gt;password store&lt;/a&gt; for&#xA;handling secrets and passwords. This tool provides the &lt;code&gt;pass&lt;/code&gt; command, and that&#xA;requires the use of &lt;code&gt;gpg&lt;/code&gt;, so let&amp;rsquo;s start by installing GPG:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you have &lt;code&gt;gpg&lt;/code&gt;, make sure you pull your private key from wherever you have&#xA;it stored (e.g. external USB stick), then execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;gpg --import &amp;lt;private-key&amp;gt;&#xA;gpg --export &amp;lt;key-id&amp;gt; # public key by default&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t forget you can &lt;em&gt;sign&lt;/em&gt; your git commits:&lt;br&gt;&#xA;&lt;code&gt;git config --global user.signingkey &amp;lt;key-id&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next, install &lt;code&gt;pass&lt;/code&gt; and &lt;code&gt;pass otp&lt;/code&gt; commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install pass pass-otp zbar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can now pass a QR code into &lt;code&gt;pass otp&lt;/code&gt; and use the terminal for generating&#xA;one-time pass codes for 2FA/MFA authentication:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;zbarimg -q --raw /tmp/qr.png | pass otp insert Work/Acme/totp/foo`  &#xA;&#xA;pass otp -c Work/Acme/totp/foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;installing &lt;code&gt;zbar&lt;/code&gt; provides the &lt;code&gt;zbarimg&lt;/code&gt; command&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Lastly, we need to setup a new Password Store, and to do that we need to provide&#xA;our GPG key id:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# &amp;lt;ref&amp;gt; needs to be your email, or part of the key&#39;s description&#xA;keyid=$(gpg --list-keys &amp;lt;ref&amp;gt; | head -n 2 | tail -n 1 | cut -d &#39; &#39; -f 7)&#xA;&#xA;pass init $keyid&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now we can pull our Password Store from a &lt;em&gt;private&lt;/em&gt; repository:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;pass git init&#xA;pass git remote add origin git@github.com:Foo/Bar.git&#xA;pass git pull&#xA;git branch --set-upstream-to=origin/master master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I also like to ensure my encrypted datastore is sync&amp;rsquo;ed up to other&#xA;online providers, and symlinked to &lt;code&gt;~/.password-store&lt;/code&gt; as well so changes are&#xA;backed up automatically in multiple places.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;mobile-password-store&#34;&gt;Mobile Password Store&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is also a &lt;a href=&#34;https://github.com/android-password-store/Android-Password-Store&#34; target=&#34;_blank&#34;&gt;mobile app for&#xA;Android&lt;/a&gt; that&#xA;you can download from the Google Play store (and other places) that allows you&#xA;to access the Password Store if it has been pushed to a distributed&#xA;version-control system such as GitHub (better still if the repository is private&#xA;&amp;ndash; &amp;ldquo;out of sight, out of mind&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To get set-up, go through the following steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Install Password Store app.&lt;/li&gt;&#xA;&lt;li&gt;Select &amp;ldquo;Clone from Server&amp;rdquo; option.&lt;/li&gt;&#xA;&lt;li&gt;Add in github credentials (e.g. &lt;code&gt;git@github.com:Foo/Bar.git&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Create new SSH key via Password Store app (give it a password).&lt;/li&gt;&#xA;&lt;li&gt;Encrypt your SSH key with symmetrical encryption (e.g. &lt;code&gt;gpg --symmetric&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Email SSH key to self.&lt;/li&gt;&#xA;&lt;li&gt;Decrypt SSH key and copy it into GitHub UI.&lt;/li&gt;&#xA;&lt;li&gt;Password Store app will ask for SSH key password, then it&amp;rsquo;ll clone the repo.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Before you can access the content of the Password Store (remember all the&#xA;content is individual GPG keys) you&amp;rsquo;ll need the GPG &lt;em&gt;private&lt;/em&gt; key in order to&#xA;decrypt files that would have been encrypted using your public key.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Export your private key as ASCII (via laptop: &lt;code&gt;gpg --armor --output passkey.txt --export-secret-keys &amp;lt;key_id&amp;gt;&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Encrypt your exported private key with symmetrical encryption (&lt;code&gt;gpg --symmetric passkey.txt&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Email your private key to yourself.&lt;/li&gt;&#xA;&lt;li&gt;Download private key to your phone.&lt;/li&gt;&#xA;&lt;li&gt;Install OpenKeychain app (via Google Play)&lt;/li&gt;&#xA;&lt;li&gt;Locate the downloaded encrypted private key and open with OpenKeychain app.&lt;/li&gt;&#xA;&lt;li&gt;Enter password used to encrypt the private key.&lt;/li&gt;&#xA;&lt;li&gt;Then click into the extracted &lt;code&gt;passkey.txt&lt;/code&gt; file and then click &amp;ldquo;Import&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;In Password Store app set the options:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Select &amp;ldquo;OpenPGP Provider&amp;rdquo; (choose: OpenKeychain)&lt;/li&gt;&#xA;&lt;li&gt;Select &amp;ldquo;OpenPGP Key id&amp;rdquo; (choose: the imported public key)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;go&#34;&gt;Go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll install the latest version of &lt;code&gt;go&lt;/code&gt; (as far as Homebrew is concerned):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is required because in order to handle different versions of &lt;code&gt;go&lt;/code&gt; we&amp;rsquo;ll&#xA;want to &lt;a href=&#34;https://gist.github.com/af300f602fa4da8cc14863f36a24bd1e&#34; target=&#34;_blank&#34;&gt;manually compile&#xA;go&lt;/a&gt;, and &lt;em&gt;that&lt;/em&gt;&#xA;ironically requires &lt;em&gt;a&lt;/em&gt; version of the go compiler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, make sure the default Go directory is set in your &lt;code&gt;$PATH&lt;/code&gt; so that any&#xA;installed binaries will be available:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export PATH=&amp;quot;$HOME/go/bin:$PATH&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;python&#34;&gt;Python&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The macOS comes only with Python 2.x and although the specific version &lt;em&gt;should&lt;/em&gt;&#xA;(according to the Python docs) have the &lt;code&gt;pip&lt;/code&gt; command available, that&amp;rsquo;s not the&#xA;case. So we have to install pip for Python2 manually using the &lt;em&gt;very old&lt;/em&gt; (but&#xA;built-in) &lt;code&gt;easy_install&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;sudo easy_install pip&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now when running &lt;code&gt;pip --version&lt;/code&gt; we should see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pip 19.0.3 from /Library/Python/2.7/site-packages/pip-19.0.3-py2.7.egg/pip (python 2.7)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point I&amp;rsquo;m going to ask you to read &lt;a href=&#34;/posts/python-app-dependencies/&#34;&gt;Python Management and Project&#xA;Dependencies&lt;/a&gt; which is separate/dedicated post&#xA;I wrote about installing multiple Python versions and how to utilize virtual&#xA;environments.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;python-packages&#34;&gt;Python Packages&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here are some packages I like to install as a general rule&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/python/black&#34; target=&#34;_blank&#34;&gt;black&lt;/a&gt;: formatter (like golang&amp;rsquo;s &lt;code&gt;gofmt&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://flake8.pycqa.org&#34; target=&#34;_blank&#34;&gt;flake8&lt;/a&gt;: linter&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/PyCQA/flake8-import-order&#34; target=&#34;_blank&#34;&gt;flake8-import-order&lt;/a&gt;: validates imports&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.mypy-lang.org&#34; target=&#34;_blank&#34;&gt;mypy&lt;/a&gt;: static analysis&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://ipython.org&#34; target=&#34;_blank&#34;&gt;ipython&lt;/a&gt;: REPL&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://pytest.org&#34; target=&#34;_blank&#34;&gt;pytest&lt;/a&gt;: testing framework&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.structlog.org/en/stable/&#34; target=&#34;_blank&#34;&gt;structlog&lt;/a&gt;: structured logging&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.tornadoweb.org&#34; target=&#34;_blank&#34;&gt;tornado&lt;/a&gt;: async web framework&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://boto3.amazonaws.com/v1/documentation/api/latest/index.html&#34; target=&#34;_blank&#34;&gt;boto3&lt;/a&gt;: AWS CLI tool&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://tox.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;tox&lt;/a&gt;: generic virtualenv management and testing tool&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for an example of how to configure Flake8 and its plugins, see &lt;a href=&#34;https://gist.github.com/0ce27db1d7294f3af9896c0807ccfeed&#34; target=&#34;_blank&#34;&gt;this&#xA;gist&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I would also strongly recommend installing the following tools:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;isort&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;autopep8&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;unimport&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a one liner to install some of these packages that I&amp;rsquo;m guaranteed to use&#xA;in all projects&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python3 -m pip install isort autopep8 unimport tox mypy flake8 flake8-import-order&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I then reference these in my &lt;code&gt;.vimrc&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot; Execute Python isort&#xA;autocmd BufWritePost *.py :execute &#39;!isort %&#39; | edit&#xA;&#xA;&amp;quot; Execute Python autopep8&#xA;autocmd BufWritePost *.py :execute \&#xA;&#39;!autopep8 --experimental --verbose --aggressive --aggressive --recursive --in-place %&#39; | edit&#xA;&#xA;&amp;quot; Execute Python unimport&#xA;autocmd BufWritePost *.py :execute &#39;!unimport --remove %&#39; | edit&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re using pipx (a tool that helps to install packages as self isolated&#xA;binaries) just be sure the &lt;code&gt;pipx ensurepath&lt;/code&gt; call doesn&amp;rsquo;t update the shell&#xA;&lt;code&gt;PATH&lt;/code&gt; by &lt;em&gt;appending&lt;/em&gt; the &lt;code&gt;/Users/integralist/.local/bin&lt;/code&gt; but by &lt;em&gt;prepending&lt;/em&gt; it&#xA;instead. This might require you to manually update your &lt;code&gt;~/.bash_profile&lt;/code&gt; like&#xA;so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;export PATH=&amp;quot;/Users/integralist/.local/bin:$PATH&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you install pipx via Homebrew then it&amp;rsquo;ll be attached to that Python&#xA;version. Meaning if you upgrade your Python version, then pipx could break&#xA;(e.g. none of the installed packages will work). The solution is to run &lt;code&gt;pipx reinstall-all --python python3&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;vim&#34;&gt;Vim&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You can either install more recent version of vim via Homebrew:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install vim&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or you can manually compile vim yourself:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I manually compile vim as I need Python3 support baked in, which&#xA;Homebrew&amp;rsquo;s version no longer does (it used to, but not any more). Python3&#xA;support means my Python linting tools will work as expected.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s start at the beginning. To manually compile Vim you would think to do&#xA;something like the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;git clone https://github.com/vim/vim.git&#xA;&#xA;cd vim&#xA;&#xA;./configure --with-features=huge \&#xA;            --enable-multibyte \&#xA;            --enable-rubyinterp=yes \&#xA;            --enable-python3interp=yes \  # relies on `brew install python3`&#xA;            --enable-perlinterp=yes \&#xA;            --enable-luainterp=yes \&#xA;            --enable-gui=gtk2 \&#xA;            --enable-cscope \&#xA;            --prefix=/usr/local&#xA;            &#xA;make &amp;amp;&amp;amp; make install&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code will copy the compiled vim binary into &lt;code&gt;/usr/local/bin&lt;/code&gt; so &lt;code&gt;which vim&lt;/code&gt; will show &lt;code&gt;/usr/local/bin/vim&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This works but I&amp;rsquo;ve found that it only works when the &lt;code&gt;python3&lt;/code&gt; interpreter is&#xA;the same version as what Vim is itself internally expecting to be available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What I mean by that is I recently upgraded my Python version to &lt;code&gt;3.7.7&lt;/code&gt; and Vim&#xA;suddenly broke. I tried the above compilation and it didn&amp;rsquo;t work. I could see&#xA;from the errors being printed that Vim was looking around my system for a Python&#xA;version &lt;code&gt;3.7.4&lt;/code&gt; which didn&amp;rsquo;t exist (hence Python3 support wasn&amp;rsquo;t compiled into&#xA;vim).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution was to firstly to tell Vim what version of Python3 to use, and&#xA;secondly (and just as important) to ignore any previously cached aspects of a&#xA;compilation (e.g. if I tell you to use Python &lt;code&gt;3.7.7&lt;/code&gt; don&amp;rsquo;t then go and try to&#xA;be helpful and use a cached run where I was using &lt;code&gt;3.7.4&lt;/code&gt; &amp;ndash; which really&#xA;confused me for a long time!):&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;now I should say, that if you can use the above example compilation&#xA;code, but just run &lt;code&gt;make clean distclean&lt;/code&gt; first, then do that! I suspect I&#xA;could have done that and Vim would have been compiled with Python &lt;code&gt;3.7.7&lt;/code&gt; just&#xA;by using the &lt;code&gt;--enable-python3interp&lt;/code&gt; flag set. I didn&amp;rsquo;t think about that at&#xA;the time though, hence the following still worked.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;make clean distclean&#xA;&#xA;./configure --with-features=huge \&#xA;  --enable-multibyte \&#xA;  --enable-rubyinterp=yes \&#xA;  --enable-python3interp=yes \&#xA;  --with-python3-command=\&#xA;  /usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/bin/python3.7 \&#xA;  --with-python3-config-dir=\&#xA;  /usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/config-3.7m-darwin/ \&#xA;  --enable-perlinterp=yes \&#xA;  --enable-luainterp=yes \&#xA;  --enable-gui=gtk2 \&#xA;  --enable-cscope \&#xA;  --prefix=/usr/local&#xA;&#xA;make &amp;amp;&amp;amp; make install&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The key flags are&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;--enable-python3interp&lt;/code&gt;: tell the compilation you want Python3 support&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--with-python3-command&lt;/code&gt;: give it a path to a Python3 interpreter/binary (†)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--with-python3-config-dir&lt;/code&gt;: a configuration directory used by the version of Python3 you want to use.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† e.g. if I run that full path in my terminal shell it&amp;rsquo;ll actually run the&#xA;Python3 REPL so I know it&amp;rsquo;s a valid path to provide.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Things get even more confusing when you are using a Python version manager like&#xA;&lt;code&gt;pyenv&lt;/code&gt; as that overrides the Python interpreter version. So although Vim might&#xA;report it&amp;rsquo;s using Python &lt;code&gt;3.7.7&lt;/code&gt; (as shown in the vim Ex command below), if you&#xA;shell out to a command like &lt;code&gt;isort&lt;/code&gt; (e.g. &lt;code&gt;!isort %&lt;/code&gt;) you&amp;rsquo;ll find that the shell&#xA;will complain no such command exists.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because the command doesn&amp;rsquo;t exist. Not for the version of Python that&amp;rsquo;s&#xA;running in the shell! The shell is running whatever version of Python &lt;code&gt;pyenv&lt;/code&gt;&#xA;has activated. So you need to make sure when you start vim that you activate a&#xA;virtual environment that has these tools available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is the Ex command to see what version of Python vim is compiled with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;:py3 import sys; print(sys.version)&#xA;&#xA;3.7.7 (default, Mar 10 2020, 15:43:03) &#xA;[Clang 11.0.0 (clang-1100.0.33.17)]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So as I mentioned, the approach I take with Vim is to activate a specific&#xA;virtual environment when in a project repo.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This could be a &lt;code&gt;pyenv&lt;/code&gt; virtual environment but actually it can just be a&#xA;standard Homebrew Python virtual environment:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# in a new shell where pyenv has no affect on the python interpreter&#xA;&#xA;python3 -m venv venv/vim&#xA;source venv/vim/bin/activate&#xA;python3 -m pip install isort autopep8 unimport tox mypy flake8 flake8-import-order&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now I know that if I start up a new shell and &lt;code&gt;cd&lt;/code&gt; to my project repo, and even&#xA;if &lt;code&gt;pyenv&lt;/code&gt; has set the python interpreter I can activate the Homebrew Python&#xA;virtual environment I created (which is going via the Homebrew installed version&#xA;of Python) and Vim will know about the packages installed in that virtual&#xA;environment.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;even if I do &lt;code&gt;python3 --version&lt;/code&gt; the shell will now report the Homebrew&#xA;version of Python (so it overrides the &lt;code&gt;pyenv&lt;/code&gt; version that might have been&#xA;set via a &lt;code&gt;.python-version&lt;/code&gt; file)!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next, I configure vim with &lt;a href=&#34;https://github.com/junegunn/vim-plug&#34; target=&#34;_blank&#34;&gt;vim-plug&lt;/a&gt;&#xA;plugin manager:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -fLo ~/.vim/autoload/plug.vim \&#xA;  --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim&#xA;curl -LSso ~/.vimrc https://raw.githubusercontent.com/Integralist/dotfiles/master/.vimrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Ensure Vim is configured with spell checking options:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;vim -E -s &amp;lt;&amp;lt;EOF&#xA;:set spell&#xA;:quit&#xA;EOF&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Install plugins by opening vim and executing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;:PlugInstall&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/junegunn/fzf&#34; target=&#34;_blank&#34;&gt;fzf&lt;/a&gt; doesn&amp;rsquo;t need a brew install when&#xA;installed via vim. See my &lt;code&gt;.vimrc&lt;/code&gt; configuration file for more details, but in&#xA;essence it contains: &lt;code&gt;Plug &#39;junegunn/fzf&#39;, { &#39;dir&#39;: &#39;~/.fzf&#39;, &#39;do&#39;: &#39;./install --all&#39; }&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Also ensure the Golang environment has what it needs by executing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;:GoInstallBinaries&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;tmux&#34;&gt;Tmux&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Install &lt;code&gt;tmux&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;brew install tmux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Configure tmux and expose &lt;code&gt;tmuxy&lt;/code&gt; command (defined in my &lt;code&gt;~/.bashrc&lt;/code&gt; for quickly&#xA;spinning up a new working environment):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;curl -LSso ~/.tmux.conf https://raw.githubusercontent.com/Integralist/dotfiles/master/.tmux.conf&#xA;curl -LSso ~/tmux.sh https://raw.githubusercontent.com/Integralist/dotfiles/master/tmux.sh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;check &lt;code&gt;$PATH&lt;/code&gt; to make sure tmux isn&amp;rsquo;t double setting values in your PATH&#xA;as it starts up. If it does you can check an older version of my&#xA;&lt;a href=&#34;https://github.com/Integralist/dotfiles/blob/cc906bd14636543e71d9c034d6507f5986a80bbd/.bash_profile#L18-L21&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;~/.bash_profile&lt;/code&gt;&lt;/a&gt;&#xA;for a work-around.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not every app can be installed via Homebrew.&#xA;&lt;a href=&#34;https://monosnap.com/welcome&#34; target=&#34;_blank&#34;&gt;Monosnap&lt;/a&gt; is one such example.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want an easy way to hide menu bar items, then try the&#xA;&lt;a href=&#34;https://apps.apple.com/app/hidden-bar/id1452453066&#34; target=&#34;_blank&#34;&gt;hidden-bar&lt;/a&gt; app&#xA;(&lt;a href=&#34;https://github.com/dwarvesf/hidden&#34; target=&#34;_blank&#34;&gt;github&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, if you&amp;rsquo;re into torrents, then the &lt;a href=&#34;https://cli-ck.io/transmission-cli-user-guide/&#34; target=&#34;_blank&#34;&gt;transmission&#xA;server/client&lt;/a&gt; (or alternatively&#xA;&lt;code&gt;npm install -g t-get&lt;/code&gt;) might be of interest to you.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;macos&#34;&gt;macOS&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be cool to configure the macOS via the terminal, things like mouse cursor&#xA;speed or keyboard repeat key performance. But unfortunately that all changed&#xA;with macOS Mojave and I couldn&amp;rsquo;t be bothered to figure out the correct way to do&#xA;it via the terminal when doing the setup via the GUI is just as quick (and I&#xA;know the few things I like to tweak off-by-heart).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, you used to be able to do things like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But since macOS Mojave those settings and namespaces seem to have changed. If&#xA;you&amp;rsquo;re interested in figuring it out, then I&amp;rsquo;d recommend starting with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;defaults read&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above command will display &lt;em&gt;all&lt;/em&gt; the current macOS settings for you. From&#xA;there you can drill down into individual namespaces like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;defaults read &amp;quot;Apple Global Domain&amp;quot; com.apple.mouse.tapBehavior&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/Integralist/dotfiles/blob/cc906bd14636543e71d9c034d6507f5986a80bbd/bootstrap.sh#L7-L53&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;are the settings I used to configure via the terminal.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;One thing I like to do is to make sure macOS&amp;rsquo; &amp;ldquo;Spaces&amp;rdquo; feature doesn&amp;rsquo;t rearrange&#xA;spaces based on their recent usage, and to do that you need to open up the&#xA;&amp;lsquo;Mission Control&amp;rsquo; settings panel and disable the option:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Automatically rearrange Spaces based on most recent use&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/laptop-setup/</guid>
      <link>https://www.integralist.co.uk/posts/laptop-setup/</link>
      <pubDate>Wed, 10 Apr 2019 00:00:00 +0000</pubDate>
      <title>New Laptop Configuration</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are times where you might be working from a particular git branch and need to quickly jump over to a different branch to do some urgent work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically you would need to first &lt;code&gt;git stash&lt;/code&gt; anything you were working on (as it&amp;rsquo;s unlikely to be in a state where it can be committed), and then you&amp;rsquo;d have to leave your current branch to create a new branch from &lt;code&gt;master&lt;/code&gt; and thus begin working on your new urgent task.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a fairly straightforward workflow, but there is a mild annoyance which is that I happen to &lt;code&gt;git stash&lt;/code&gt; &lt;em&gt;a lot&lt;/em&gt; and I find when jumping over to a new branch to do some urgent work that I might end up &lt;code&gt;git stash&lt;/code&gt;&amp;lsquo;ing a few more times along the way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately, when I&amp;rsquo;m done with my urgent task and ready to go back to my other branch, I then have to sift through my stash to find the relevant one I want to pop. OK so not that tragic considering &lt;code&gt;git stash list&lt;/code&gt; will indicate the branch on which the stash was taken (which helps), but I do then need to Google what the syntax is for popping a specific stash (e.g. it&amp;rsquo;s &lt;code&gt;git stash apply stash@{n}&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the index you want to apply.)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for the life of me I wish I could remember the syntax but it just eludes me every time.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Oh, and then you have to think about whether you actually want to use &lt;code&gt;apply&lt;/code&gt;, which leaves the stashed changes in the stack, or if you meant to actually &lt;code&gt;pop&lt;/code&gt; the stashed content (&lt;code&gt;git stash pop stash@{n}&lt;/code&gt;) so it&amp;rsquo;s properly removed from the stack.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where I was recently introduced to a concept in git referred to as a &amp;lsquo;worktree&amp;rsquo; (thanks Kiran).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;worktree&#34;&gt;Worktree&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Git offers a feature referred to as a &lt;a href=&#34;https://git-scm.com/docs/git-worktree&#34; target=&#34;_blank&#34;&gt;worktree&lt;/a&gt;, and what it does is allow you to have multiple branches running at the same time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It does this by creating a new directory for you with a copy of your git repository that is synced between the two directories where they are stored.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is different to manually creating a new directory and git cloning your repo down, because with the worktree model the two sub directories are aware of each other.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as you&amp;rsquo;ll see, although this workflow is pretty cool, you &lt;em&gt;could&lt;/em&gt; argue that &lt;code&gt;git stash&lt;/code&gt; is just plain simpler and easier for a human mind to reason about. I&amp;rsquo;ll leave that up to the reader to decide.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In the following example I&amp;rsquo;m going to create a new git repo. I&amp;rsquo;ll make a change in &lt;code&gt;master&lt;/code&gt;, then create a new branch for doing some work. We&amp;rsquo;ll then imagine that I have been given an urgent task that I must complete &lt;em&gt;now&lt;/em&gt; and yet my current non-master branch is in such a state that I want to avoid just stashing everything.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I use tmux to split my terminal into multiple windows, and this demonstration will require two windows (or two separate terminal instances if you&amp;rsquo;re not using a screen multiplexer) for the sake of demonstration.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;create-a-new-repo&#34;&gt;Create a new repo&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;mkdir foo_project&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cd foo_project&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;touch foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git add foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git commit -m &amp;quot;created foo file&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;create-a-new-branch&#34;&gt;Create a new branch&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git checkout -b foo_contents&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;echo 123 &amp;gt; foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git add -u&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git commit -m &amp;quot;added content to foo&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now I&amp;rsquo;ll create a new file and stage it for committing, but I won&amp;rsquo;t commit it (this is where we pretend my branch is in some hideously complex state).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;create-new-worktree-branch&#34;&gt;Create new worktree branch&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git worktree add ../foo_hotfix&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll want to create the new worktree in a directory outside of your current repo&amp;rsquo;s directory (just so there&amp;rsquo;s a clear distinction).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;At this point you&amp;rsquo;ll find your current terminal is still in the same &lt;code&gt;foo_contents&lt;/code&gt;, but there is now a new directory called &lt;code&gt;foo_hotfix&lt;/code&gt; outside your current repo&amp;rsquo;s directory.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;make-changes-in-new-worktree-branch&#34;&gt;Make changes in new worktree branch&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Open up a new terminal (or split window) and run through the following steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cd ./foo_hotfix&lt;/code&gt; (or &lt;code&gt;cd ../foo_hotfix&lt;/code&gt; if your new terminal is currently set to your main git repo directory)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git log&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;OK, so if you do a &lt;code&gt;git log&lt;/code&gt; you&amp;rsquo;ll find that the worktree has a branch automatically created and named after the worktree (so the branch is called &lt;code&gt;foo_hotfix&lt;/code&gt; in my case).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The important thing to realize is that &lt;code&gt;git worktree add&lt;/code&gt; is a bit like &lt;code&gt;git branch&lt;/code&gt; in that it creates the new worktree from the current branch you&amp;rsquo;re in. Meaning that my &lt;code&gt;foo_hotfix&lt;/code&gt; branch has the &amp;ldquo;added content to foo&amp;rdquo; commit from the &lt;code&gt;foo_contents&lt;/code&gt; branch as that&amp;rsquo;s where I ran the &lt;code&gt;git worktree add&lt;/code&gt; command from.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is what &lt;code&gt;git log&lt;/code&gt; looks like for me in this new worktree:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* d374dcb (Integralist) - (HEAD -&amp;gt; foo_hotfix, foo_contents) added content to foo (2 minutes ago)&#xA;* 9ae3a7f (Integralist) - (master) created foo file (3 minutes ago)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t want the commit &lt;code&gt;d374dcb&lt;/code&gt; in there as it&amp;rsquo;s coming from a branch (&lt;code&gt;foo_contents&lt;/code&gt;) that&amp;rsquo;s still in progress, and so I&amp;rsquo;ll need to rebase out that commit:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git rebase -i 9ae3a7f&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the rebase editor opens and I change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;drop&lt;/code&gt; to get rid of the commit.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now at this point I have a new working directory that I can work in:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;echo hotfix &amp;gt; baz&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git add baz&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git commit -m &amp;quot;some hotfix&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;merge-my-hotfix-back-into-master&#34;&gt;Merge my hotfix back into master&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m going to change into my &lt;code&gt;master&lt;/code&gt; branch, but remember I&amp;rsquo;m still in the &lt;code&gt;foo_hotfix&lt;/code&gt; directory, so my main repo directory &lt;code&gt;foo_project&lt;/code&gt; (open in another terminal window) is still in the &lt;code&gt;foo_contents&lt;/code&gt; branch).&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git checkout master&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git merge foo_hotfix&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;removing-the-worktree&#34;&gt;Removing the worktree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, so at this point we&amp;rsquo;ve merged our hotfix into &lt;code&gt;master&lt;/code&gt;. I want to go back to my original repo directory and make sure I have the latest &lt;code&gt;master&lt;/code&gt; rebased in before continuing on with my &lt;code&gt;foo_contents&lt;/code&gt; work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To remove the worktree you can either remove it using the git interface (e.g. &lt;code&gt;git worktree remove foo_hotfix&lt;/code&gt;) or manually remove it (e.g. &lt;code&gt;cd ../ &amp;amp;&amp;amp; rm ./foo_hotfix&lt;/code&gt;), where git will, at some point in the future, internally run a prune and remove any references to this orphaned branch/working tree (you could also manually trigger that prune using &lt;code&gt;git worktree prune&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if I do &lt;code&gt;git worktree remove foo_hotfix&lt;/code&gt; while currently residing inside the &lt;code&gt;foo_hotfix&lt;/code&gt; directory, I&amp;rsquo;ll find that the &lt;code&gt;.git&lt;/code&gt; repository is removed from the directory.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;continuing-working-on-my-feature-branch&#34;&gt;Continuing working on my feature branch&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Presuming I&amp;rsquo;m still in the &lt;code&gt;foo_hotfix&lt;/code&gt; directory and that&amp;rsquo;s where I ran &lt;code&gt;git worktree remove foo_hotfix&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cd ../foo_project&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git rebase master&lt;/code&gt; &amp;lt; whoops! I need to stash my changes first †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git stash pop&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† why yes, this does seem a bit strange considering that&amp;rsquo;s what I was trying to avoid in the first place, but in this case it&amp;rsquo;s a single &amp;lsquo;stash&amp;rsquo; and so a simple &lt;code&gt;git stash pop&lt;/code&gt; will suffice to get me back to where I need to be.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;I can now continue working on my &lt;code&gt;foo_contents&lt;/code&gt; branch.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, this was fun heh! 😉&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Do you think you have any uses for git&amp;rsquo;s worktree feature?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let me know on &lt;a href=&#34;https://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;twitter&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/git-multiple-branches/</guid>
      <link>https://www.integralist.co.uk/posts/git-multiple-branches/</link>
      <pubDate>Fri, 22 Mar 2019 00:00:00 +0000</pubDate>
      <title>Multiple Branches in Git</title>
    </item>
    <item>
      <description>&lt;p&gt;In this post I&amp;rsquo;ll be demonstrating a few common algorithms using the Python language. I&amp;rsquo;m only covering a very small subset of popular algorithms because otherwise this would become a long and diluted list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead I&amp;rsquo;m going to focus specifically on algorithms that I find useful and are important to know and understand:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Sorting&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#merge-sort&#34;&gt;Merge Sort&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#quick-sort&#34;&gt;Quick Sort&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Searching&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#binary-search&#34;&gt;Binary Search&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#breadth-first-search&#34;&gt;Breadth First Search&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#depth-first-search&#34;&gt;Depth First Search&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#dijkstra-s-algorithm&#34;&gt;Dijkstra&amp;rsquo;s Algorithm&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Three out of the four &amp;lsquo;search&amp;rsquo; algorithms listed above will be implemented around a graph data struture. Graphs appear everywhere in life. For example, your Facebook list of friends, mutual friends, and extended friends (i.e. friends of your friends who you don&amp;rsquo;t know) is a perfect example of a &amp;lsquo;graph&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Graphs can also be &amp;lsquo;weighted&amp;rsquo;, so they can indicate that a relationship between two nodes within the graph are possibly stronger than another connection, and is typically used in road maps for determining the quickest path to a particular node (we&amp;rsquo;ll come back to this later when reviewing &lt;a href=&#34;#dijkstra-s-algorithm&#34;&gt;Dijkstra&amp;rsquo;s Algorithm&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;merge-sort&#34;&gt;Merge Sort&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Given an unsorted list of integers, the merge sort algorithm enables us to sort the list.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Best: &lt;code&gt;Ω(n log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Average: &lt;code&gt;O(n log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Worst: &lt;code&gt;O(n log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Recursively split given list into two partitions.&lt;/li&gt;&#xA;&lt;li&gt;Divide the list until reaching its smallest partition.&lt;/li&gt;&#xA;&lt;li&gt;Recursively merge each pair of partitions (repeat till reconstructed list).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;That short list actually defines two distinct processes: a &amp;lsquo;break up into partitions&amp;rsquo; step followed by a &amp;lsquo;merge&amp;rsquo; step. The merge pseudo-steps could be further broken down to look something like the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To merge two partitions we iterate over each of them.&lt;/li&gt;&#xA;&lt;li&gt;Compare elements from both partitions (left and right).&lt;/li&gt;&#xA;&lt;li&gt;Append smaller element to new &amp;lsquo;results&amp;rsquo; (i.e. sorted) list.&lt;/li&gt;&#xA;&lt;li&gt;After comparing the elements, increment index for winning partition.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The above merge steps process is carried out against each recursively sorted set of partitions, and is done until we reach a final &amp;lsquo;sorted&amp;rsquo; list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an implementation of this sorting algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def merge(left, right):&#xA;    left_index, right_index = 0, 0&#xA;    result = []&#xA;&#xA;    while left_index &amp;lt; len(left) and right_index &amp;lt; len(right):&#xA;        if left[left_index] &amp;lt; right[right_index]:&#xA;            result.append(left[left_index])&#xA;            left_index += 1&#xA;        else:&#xA;            result.append(right[right_index])&#xA;            right_index += 1&#xA;&#xA;    result += left[left_index:]&#xA;    result += right[right_index:]&#xA;&#xA;    return result&#xA;&#xA;&#xA;def merge_sort(collection):&#xA;    if len(collection) &amp;lt;= 1:&#xA;        print(&#39;collection is &amp;lt;= 1\n&#39;)&#xA;        return collection&#xA;&#xA;    middle = len(collection) // 2&#xA;    left = collection[:middle]&#xA;    right = collection[middle:]&#xA;&#xA;    left = merge_sort(left)&#xA;    right = merge_sort(right)&#xA;&#xA;    return merge(left, right)&#xA;&#xA;collection = [10, 5, 2, 3, 7, 0, 9, 12]&#xA;&#xA;result = merge_sort(collection)&#xA;&#xA;print(f&#39;merge sort of {collection} result: {result}\n\n&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-sort&#34;&gt;Quick Sort&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Given an unsorted list of integers, the merge sort algorithm enables us to sort the list.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Best: &lt;code&gt;Ω(n log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Average: &lt;code&gt;O(n log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Worst: &lt;code&gt;O(n^2)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Pick a &amp;lsquo;pivot&amp;rsquo; (e.g. random index from the list).&lt;/li&gt;&#xA;&lt;li&gt;Iterate the collection twice, creating two new lists.&lt;/li&gt;&#xA;&lt;li&gt;Create a list consisting of elements less than pivot.&lt;/li&gt;&#xA;&lt;li&gt;Create a list consisting of elements greater than pivot.&lt;/li&gt;&#xA;&lt;li&gt;function return value is &lt;code&gt;fn(less) + pivot + fn(greater)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;notice the &amp;lsquo;less&amp;rsquo; and &amp;lsquo;greater&amp;rsquo; lists are passed recursively back through the quick sort function.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Below is an implementation of this sorting algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from random import randrange&#xA;&#xA;collection = [10, 5, 2, 3, 7, 0, 9, 12]&#xA;&#xA;def quicksort(collection):&#xA;    if len(collection) &amp;lt; 2:&#xA;        return collection&#xA;    else:&#xA;        random = randrange(0, len(collection))&#xA;        pivot = collection.pop(random)&#xA;&#xA;        less = [i for i in collection if i &amp;lt;= pivot]&#xA;        greater = [i for i in collection if i &amp;gt; pivot]&#xA;&#xA;        return quicksort(less) + [pivot] + quicksort(greater)&#xA;&#xA;cloned_collection = collection.copy()  # avoid mutation&#xA;&#xA;result = quicksort(cloned_collection)&#xA;&#xA;print(f&#39;quick sort of {collection} result: {result}\n\n&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;difference-between-merge-and-quick-sort&#34;&gt;Difference between Merge and Quick sort&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Both merge sort and quick sort are &amp;lsquo;divide and conquer&amp;rsquo; algorithms, e.g. they divide a problem up into two and then process the individual partitions, and will keep dividing up the problem for as a long as it can.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So when considering which you should use (i.e. which is better?) you&amp;rsquo;ll find merge sort is more performant because its particular implementation is more efficient with the operations it carries out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically, the difference between merge sort and quick sort is that with quick sort you&amp;rsquo;ll loop over the collection twice in order to create two partitions, but remember that doing so doesn&amp;rsquo;t mean the partitions are sorted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These quick sort partitions are not sorted until the recursive calls end up with a small enough partition (length of 1) where the left and right partitions can be analyzed, joined and therefore considered &amp;lsquo;sorted&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Compare that to merge sort which recursively creates multiple partitions (all the way down to the smallest possible partition) &lt;em&gt;before&lt;/em&gt; it then recursively rolls back up the execution stack and attempts to sort each of the partitions along the way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, with a merge sort it&amp;rsquo;s possible to parallelize the data over multiple processes, while quick sort requires data to be processed within a single process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means that quick sort has potentially more operations to be carried out than merge sort, and therefore has a greater time complexity. Although quick sort can offer better &amp;lsquo;space&amp;rsquo; complexity (worst case: &lt;code&gt;O(log(n))&lt;/code&gt;) compared to merge sort (worst case: &lt;code&gt;O(n)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All that said, the implementation of the algorithms can be tweaked as needed to produce better or worst performance. For example, quick sort could be modified to use another algorithm called &lt;a href=&#34;https://en.wikipedia.org/wiki/Introsort&#34; target=&#34;_blank&#34;&gt;intro sort&lt;/a&gt; which is a mix of quick sort, insertion sort, and heapsort, that&amp;rsquo;s worst-case &lt;code&gt;O(n log(n))&lt;/code&gt; but retains the speed of quick sort in most cases.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;radix-search&#34;&gt;Radix Search?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Another searching algorithm that I see crop up in discussions every now and then is &amp;lsquo;radix search&amp;rsquo;. The way it works is to loop over your data structure &lt;em&gt;twice&lt;/em&gt; and (if we&amp;rsquo;re dealing with integers) for the first iteration you&amp;rsquo;ll &amp;lsquo;bucket&amp;rsquo; the elements by their 1&amp;rsquo;s digit, followed by another iteration to bucket the elements by their 10&amp;rsquo;s digit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with a collection like &lt;code&gt;25, 17, 85, 94, 32, 79&lt;/code&gt;, after the first iteration we would have created &amp;lsquo;numbered&amp;rsquo; buckets that looked something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1: &amp;lt;empty&amp;gt;&#xA;2: 32&#xA;3: &amp;lt;empty&amp;gt;&#xA;4: 94&#xA;5: 25, 85&#xA;6: &amp;lt;empty&amp;gt;&#xA;7: 17&#xA;8: &amp;lt;empty&amp;gt;&#xA;9: 79&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we remove the empty buckets it means we&amp;rsquo;ll end up with a partially sorted list of &lt;code&gt;32, 94, 25, 85, 17, 79&lt;/code&gt;. Now for the second iteration we re-bucket by the 10&amp;rsquo;s, so this means we end up with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1: 17&#xA;2: 25&#xA;3: 32&#xA;4: &amp;lt;empty&amp;gt;&#xA;5: &amp;lt;empty&amp;gt;&#xA;6: &amp;lt;empty&amp;gt;&#xA;7: 79&#xA;8: 85&#xA;9: 94&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again if we remove the empty buckets we&amp;rsquo;ll find we now have a fully sorted list: &lt;code&gt;17, 25, 32, 79, 85, 94&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s an interesting algorithm but ultimately is quite limited and so other sorting algorithms like merge/quick sort are generally preferred. Some constraints to be aware of are is that it&amp;rsquo;s generally less efficient than other comparison sorting algorithms.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Radix sort is also targeted at integers, fixed size strings, floating points and &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt; or lexicographic order comparison predicates.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;binary-search&#34;&gt;Binary Search&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The most popular algorithm (by far) for searching a value in a &lt;em&gt;sorted&lt;/em&gt; list is &amp;lsquo;binary search&amp;rsquo;. The reason for its popularity is that it provides &lt;a href=&#34;/posts/algorithmic-complexity-in-python/#logarithmic-time&#34;&gt;logarithmic performance&lt;/a&gt; (on average) for access, search, insertion and deletion operations.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Average: &lt;code&gt;O(log(n))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Worst: &lt;code&gt;O(n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;define &amp;lsquo;start&amp;rsquo; and &amp;lsquo;end&amp;rsquo; positions (usually length of list).&lt;/li&gt;&#xA;&lt;li&gt;locate middle of list.&lt;/li&gt;&#xA;&lt;li&gt;stop searching if correct value found.&lt;/li&gt;&#xA;&lt;li&gt;if value is greater: change end position to the middle index.&lt;/li&gt;&#xA;&lt;li&gt;if value is smaller: change start position to the middle index.&lt;/li&gt;&#xA;&lt;li&gt;repeat above steps until value is found.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;What this ultimately achieves is shortening the search &amp;lsquo;window&amp;rsquo; of items by half each time (that&amp;rsquo;s the logarithmic part). So if you have a list of 1000 elements, then we can say it&amp;rsquo;ll take a maximum of ten operations to find the number you&amp;rsquo;re looking for (that&amp;rsquo;s: &lt;code&gt;log 2(10)&lt;/code&gt; == &lt;code&gt;2^10&lt;/code&gt; == &lt;code&gt;1024&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s outstanding.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an implementation of this popular search algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def binary_search(collection, item):&#xA;    start = 0&#xA;    stop = len(collection) - 1&#xA;&#xA;    while start &amp;lt;= stop:&#xA;        middle = round((start + stop) / 2)&#xA;        guess = collection[middle]&#xA;&#xA;        if guess == item:&#xA;            return middle&#xA;        if guess &amp;gt; item:&#xA;            stop = middle - 1&#xA;        else:&#xA;            start = middle + 1&#xA;&#xA;    return None&#xA;&#xA;collection = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 20, 21]&#xA;&#xA;result = binary_search(collection, 9)&#xA;&#xA;print(f&#39;the value was found at index {result}\n\n&#39;)  # index 4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you could swap &lt;code&gt;round((start + stop) / 2)&lt;/code&gt; for &lt;code&gt;(start + stop) // 2&lt;/code&gt; which uses Python&amp;rsquo;s &lt;code&gt;//&lt;/code&gt; floor division operator, but I typically opt for the clarity of using the explicit &lt;code&gt;round&lt;/code&gt; function.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;breadth-first-search&#34;&gt;Breadth First Search&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A BFS (breadth first search) is an algorithm that searches a data structure from either a root node or some arbitrary starting point. It does this by exploring all the neighbouring nodes, before moving onto other connected nodes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following graph represents a group of people. Some people know each other (e.g. both Alice and Bob know each other), where as other people don&amp;rsquo;t (e.g. Dave knows Ethan, but Ethan knows no one else in this group).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/graph-bfs.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/graph-bfs.png&#34; alt=&#34;graph bfs&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll use the BFS (breadth first search) algorithm to locate &amp;lsquo;Ethan&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The time complexity of this algorithm will be, at worst, &lt;code&gt;O(V+E)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the case of dealing with a graph, &lt;code&gt;V&lt;/code&gt; = vertex (a node in the graph) and &lt;code&gt;E&lt;/code&gt; = edge (the line between nodes), the worst case scenario will mean we have to explore every edge and node.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Pick a starting point in the data structure.&lt;/li&gt;&#xA;&lt;li&gt;Track nodes to process (e.g. a queue).&lt;/li&gt;&#xA;&lt;li&gt;While the queue has content:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Take a node from the queue.&lt;/li&gt;&#xA;&lt;li&gt;If the node has been searched already, then skip it.&lt;/li&gt;&#xA;&lt;li&gt;If not searched, check if it&amp;rsquo;s a match, otherwise update queue.&lt;/li&gt;&#xA;&lt;li&gt;Queue should be updated with that node&amp;rsquo;s adjacent nodes.&lt;/li&gt;&#xA;&lt;li&gt;If match is found, then exit the queue loop.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Below is our example implementation of the BFS algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import random&#xA;from collections import deque&#xA;&#xA;graph = {&#39;alice&#39;: [&#39;bob&#39;, &#39;charlie&#39;, &#39;dave&#39;],&#xA;         &#39;bob&#39;: [&#39;alice&#39;, &#39;charlie&#39;],&#xA;         &#39;charlie&#39;: [&#39;alice&#39;, &#39;bob&#39;],&#xA;         &#39;dave&#39;: [&#39;alice&#39;, &#39;ethan&#39;]}&#xA;&#xA;def search(starting_point, name):&#xA;    print(f&#39;starting point: {starting_point}&#39;)&#xA;&#xA;    queue = deque()&#xA;    queue += graph[starting_point]  # add starting_point&#39;s neighbours&#xA;    print(f&#39;queue: {queue}&#39;)&#xA;&#xA;    searched = []&#xA;&#xA;    while queue:&#xA;        person = queue.popleft()&#xA;        print(f&#39;person: {person}&#39;)&#xA;&#xA;        if person not in searched:&#xA;            if person == name:&#xA;                print(f&#39;found a match: {person}&#39;)&#xA;                return True&#xA;            else:&#xA;                queue += graph[person]  # add this item&#39;s neighbours&#xA;                print(f&#39;queue updated: {queue}&#39;)&#xA;                searched.append(person)&#xA;        else:&#xA;            print(f&#39;skipping {person} as they have already been searched&#39;)&#xA;&#xA;    return False&#xA;&#xA;starting_point = random.choice(list(graph.keys()))&#xA;search(starting_point, &#39;ethan&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;an alternative implementation might use Python&amp;rsquo;s &lt;code&gt;set&lt;/code&gt; data structure to avoid having to filter already searched people.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at the first run of this program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;starting point: dave&#xA;queue: deque([&#39;alice&#39;, &#39;ethan&#39;])&#xA;person: alice&#xA;queue updated: deque([&#39;ethan&#39;, &#39;bob&#39;, &#39;charlie&#39;, &#39;dave&#39;])&#xA;person: ethan&#xA;found a match: ethan&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From that output we can see that we started very conveniently at the &amp;lsquo;Dave&amp;rsquo; node. Dave&amp;rsquo;s adjacent nodes are Alice and Ethan. Due to the order of the nodes in the queue we attempt to process Alice next. Then we check the next node (Ethan) and find what we&amp;rsquo;re looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now consider a second run which has a different starting point (notice the difference in the number of operations):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;starting point: charlie&#xA;queue: deque([&#39;alice&#39;, &#39;bob&#39;])&#xA;person: alice&#xA;queue updated: deque([&#39;bob&#39;, &#39;bob&#39;, &#39;charlie&#39;, &#39;dave&#39;])&#xA;person: bob&#xA;queue updated: deque([&#39;bob&#39;, &#39;charlie&#39;, &#39;dave&#39;, &#39;alice&#39;, &#39;charlie&#39;])&#xA;person: bob&#xA;person: charlie&#xA;queue updated: deque([&#39;dave&#39;, &#39;alice&#39;, &#39;charlie&#39;, &#39;alice&#39;, &#39;bob&#39;])&#xA;person: dave&#xA;queue updated: deque([&#39;alice&#39;, &#39;charlie&#39;, &#39;alice&#39;, &#39;bob&#39;, &#39;alice&#39;, &#39;ethan&#39;])&#xA;person: alice&#xA;skipping alice as they have already been searched&#xA;person: charlie&#xA;skipping charlie as they have already been searched&#xA;person: alice&#xA;skipping alice as they have already been searched&#xA;person: bob&#xA;skipping bob as they have already been searched&#xA;person: alice&#xA;skipping alice as they have already been searched&#xA;person: ethan&#xA;found a match: ethan&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve used a dict to represent a graph, which helped to make the code simpler to understand. A different data structure (e.g. a directed tree) would require a different implementation of the algorithm. Remember, the basic premise is to search a graph node&amp;rsquo;s adjacent fields, and then their adjacent nodes.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;depth-first-search&#34;&gt;Depth First Search&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following image shows a tree structure that represents various people&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/graph-dfs.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/graph-dfs.png&#34; alt=&#34;graph dfs&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A DFS (depth first search) is an algorithm that searches a data structure (such as a tree, or a graph) from its root node. It searches &lt;em&gt;downwards&lt;/em&gt; through each child node until there are no more children.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll use the DFS (depth first search) algorithm to locate the node &amp;lsquo;Ethan&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using our example tree structure (above) we would start with Alice, then check the first child Bob. Bob has no children so we would move onto Charlie. Charlie has a single child Fred so we would check him next. Fred has no children so we start back up at Dave. Finally, we check the child of Dave which is Ethan.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice how if don&amp;rsquo;t find a match for what we&amp;rsquo;re looking for, then we backtrack up to the top of the tree and start again at the root node&amp;rsquo;s next child node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The time complexity of this algorithm will be, at worst, &lt;code&gt;O(V+E)&lt;/code&gt; (as noted with Breath First Search, this means we could end up hitting every single node and edge in the data struture).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this example uses a traditional tree data structure instead of a graph to represent the underlying data to be searched.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Start at the root node.&lt;/li&gt;&#xA;&lt;li&gt;Check first child to see if it&amp;rsquo;s a match.&lt;/li&gt;&#xA;&lt;li&gt;If not a match, check that child&amp;rsquo;s children.&lt;/li&gt;&#xA;&lt;li&gt;Keep checking the children until a match is found.&lt;/li&gt;&#xA;&lt;li&gt;If no children are a match, then start from next highest node.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Below is our example implementation of the DFS algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Tree(object):&#xA;    def __init__(self, name=&#39;root&#39;, children=None):&#xA;        self.name = name&#xA;        self.children = []&#xA;&#xA;        if children is not None:&#xA;            for child in children:&#xA;                self.add_child(child)&#xA;&#xA;    def __repr__(self):&#xA;        return self.name&#xA;&#xA;    def add_child(self, node):&#xA;        assert isinstance(node, Tree)&#xA;        self.children.append(node)&#xA;&#xA;&#xA;tree = Tree(&#39;Alice&#39;, [Tree(&#39;Bob&#39;),&#xA;                      Tree(&#39;Charlie&#39;, [Tree(&#39;Fred&#39;)]),&#xA;                      Tree(&#39;Dave&#39;, [Tree(&#39;Ethan&#39;)])])&#xA;&#xA;&#xA;def search_tree(tree, node):&#xA;    print(f&#39;current tree: {tree}&#39;)&#xA;&#xA;    if tree.name == node:&#xA;        print(f&#39;found node: {node} in {tree}&#39;)&#xA;        return tree&#xA;&#xA;    for child in tree.children:&#xA;        print(f&#39;current child: {child}&#39;)&#xA;&#xA;        if child.name == node:&#xA;            print(f&#39;found node: {node} in {child}&#39;)&#xA;            return child&#xA;&#xA;        if child.children:&#xA;            print(f&#39;attempt searching {child} for {node}&#39;)&#xA;            match = search_tree(child, node)&#xA;&#xA;            if match:&#xA;                print(f&#39;returning the match: {match}&#39;)&#xA;                return match&#xA;&#xA;result = search_tree(tree, &#39;Ethan&#39;)&#xA;&#xA;print(f&#39;result: {result}&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in our example we use a simple tree data structure to represent the data to be searched. Our implementation is designed to work with that structure. So, for example, if we had multiple children per node (left and right child nodes), then we would need to account for the backtrack to the relevant child right node near the top of the tree.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at the output of this program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;current tree: Alice&#xA;current child: Bob&#xA;current child: Charlie&#xA;attempt searching Charlie for Ethan&#xA;current tree: Charlie&#xA;current child: Fred&#xA;current child: Dave&#xA;attempt searching Dave for Ethan&#xA;current tree: Dave&#xA;current child: Ethan&#xA;found node: Ethan in Ethan&#xA;returning the match: Ethan&#xA;result: Ethan&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So from this output we can see we started at Alice, and first checked Bob but because Bob has no children we moved back up to Charlie. From Charlie we go down to Fred but as there&amp;rsquo;s no more children we move back up to Dave. Finally we check Dave&amp;rsquo;s children to find Ethan.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;when-to-choose-bfs-vs-dfs&#34;&gt;When to choose BFS vs DFS?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Generally BFS is better when dealing with relationships across fields, where as DFS is better suited to tree hierarchies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That said, below is a short list of things to consider when opting for either a BFS or DFS:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the data strutures used (including the implementation of your algorithm) can also contribute to your decision.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you know the result is not far from the root: BFS.&lt;/li&gt;&#xA;&lt;li&gt;If result(s) are located deep in the structure then: DFS.&lt;/li&gt;&#xA;&lt;li&gt;If the depth of the structure is &lt;em&gt;very&lt;/em&gt; deep, then in some cases: BFS.&lt;/li&gt;&#xA;&lt;li&gt;If the width of the structure is &lt;em&gt;very&lt;/em&gt; wide, then memory consumption could mean: DFS.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Ultimately, it all depends.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;searching-an-unsorted-collection&#34;&gt;Searching an unsorted collection?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have an unsorted collection, then your only option for searching is a linear time complexity &lt;code&gt;O(n)&lt;/code&gt;. To improve that performance we would need to first sort the collection so we could use a binary search on it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another potential option is to run a linear search across multiple CPU cores so you&amp;rsquo;re effectively parallelizing the processing. It&amp;rsquo;s still &lt;code&gt;O(n)&lt;/code&gt; linear time complexity, but the perceived time would be shorter (depending on the restructuring of the collection split chunks).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dijkstra-s-algorithm&#34;&gt;Dijkstra&amp;rsquo;s Algorithm&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The Dijkstra algorithm tells you the quickest path from A to B within a weighted graph.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/graph-weighted.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/graph-weighted.png&#34; alt=&#34;graph weighted&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above graph we have a few options:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Start &amp;gt; A &amp;gt; End (Cost: 7)&lt;/li&gt;&#xA;&lt;li&gt;Start &amp;gt; B &amp;gt; End (Cost: 7)&lt;/li&gt;&#xA;&lt;li&gt;Start &amp;gt; B &amp;gt; A &amp;gt; End (Cost: 6)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as you can see, the route that visually looks longer is actually quicker when considering the weighted nature of the graph.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The time complexity of this algorithm will be, at worst, &lt;code&gt;O(V+E)&lt;/code&gt; (as noted with Breath First Search and Depth First Search, this means we could end up hitting every single node and edge in the data struture).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The algorithm can be broken down into the following pseudo-steps (it&amp;rsquo;s important to note that in this implementation we calculate the route in reverse):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Identify the lowest cost node in our graph.&lt;/li&gt;&#xA;&lt;li&gt;Acquire the adjacent nodes.&lt;/li&gt;&#xA;&lt;li&gt;Update costs for each node while accounting for surrounding nodes.&lt;/li&gt;&#xA;&lt;li&gt;Track the processed nodes.&lt;/li&gt;&#xA;&lt;li&gt;Check for new lowest cost node.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;These steps are very specific to our graph, so if your data structure is different, then the implementation of the algorithm will need to change to reflect those differences. Regardless this should be a nice introduction to the fundamental properties of the algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Without further ado, below is an example implementation of the Dijkstra&amp;rsquo;s algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;graph = {&#xA;    &#39;start&#39;: {&#xA;        &#39;a&#39;: 6,&#xA;        &#39;b&#39;: 2&#xA;    },&#xA;    &#39;a&#39;: {&#xA;        &#39;end&#39;: 1&#xA;    },&#xA;    &#39;b&#39;: {&#xA;        &#39;a&#39;: 3,&#xA;        &#39;end&#39;: 5&#xA;    },&#xA;    &#39;end&#39;: {}&#xA;}&#xA;&#xA;costs = {&#xA;    &#39;a&#39;: 6,&#xA;    &#39;b&#39;: 2,&#xA;    &#39;end&#39;: float(&#39;inf&#39;)  # set to infinity until we know the cost to reach&#xA;}&#xA;&#xA;parents = {&#xA;    &#39;a&#39;: &#39;start&#39;,&#xA;    &#39;b&#39;: &#39;start&#39;,&#xA;    &#39;end&#39;: None  # doesn&#39;t have one yet until we choose either &#39;a&#39; or &#39;b&#39;&#xA;}&#xA;&#xA;processed = []&#xA;route = []&#xA;&#xA;def find_lowest_cost_node(costs):&#xA;    lowest_cost = float(&#39;inf&#39;)&#xA;    lowest_cost_node = None&#xA;&#xA;    for node in costs:&#xA;        cost = costs[node]&#xA;&#xA;        if cost &amp;lt; lowest_cost and node not in processed:&#xA;            lowest_cost = cost&#xA;            lowest_cost_node = node&#xA;&#xA;    return lowest_cost_node&#xA;&#xA;def find_fastest_path():&#xA;    node = find_lowest_cost_node(costs)&#xA;&#xA;    while node is not None:&#xA;        cost = costs[node]&#xA;        neighbours = graph[node]&#xA;&#xA;        for n in neighbours.keys():&#xA;            new_cost = cost + neighbours[n]&#xA;&#xA;            if costs[n] &amp;gt; new_cost:&#xA;                costs[n] = new_cost&#xA;                parents[n] = node&#xA;        processed.append(node)&#xA;        node = find_lowest_cost_node(costs)&#xA;&#xA;def display_route(node=None):&#xA;    if not node:&#xA;        route.append(&#39;end&#39;)&#xA;        display_route(parents[&#39;end&#39;])&#xA;    elif node == &#39;start&#39;:&#xA;        route.append(node)&#xA;        reverse_route = list(reversed(route))&#xA;        print(&#39;Fastest Route: &#39; + &#39; -&amp;gt; &#39;.join(reverse_route))&#xA;    else:&#xA;        route.append(node)&#xA;        display_route(parents[node])&#xA;&#xA;find_fastest_path()  # mutates global &#39;costs&#39; &amp;amp; &#39;parents&#39; arrays&#xA;display_route()  # Fastest Route: start -&amp;gt; b -&amp;gt; a -&amp;gt; end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of this program is (as expected):&lt;br&gt;&#xA;&lt;code&gt;Fastest Route: start -&amp;gt; b -&amp;gt; a -&amp;gt; end&lt;/code&gt;.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/algorithms-in-python/</guid>
      <link>https://www.integralist.co.uk/posts/algorithms-in-python/</link>
      <pubDate>Wed, 13 Mar 2019 00:00:00 +0000</pubDate>
      <title>Algorithms in Python</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I was asked on twitter recently about how I am able to be successful and impactful at an organization as a remote worker. What follows is a run down of how I work remotely, and how it has changed over the last seven years.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is &lt;em&gt;not&lt;/em&gt; a &amp;ldquo;rules for how you should do remote working&amp;rdquo; but more so a single perspective on the problem of remote working and my own simplified set of guidelines that I feel have worked for me.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-remote&#34;&gt;Why Remote?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start off by talking about why I am a remote worker. I typically work for organizations who have an office in Central London, while my home is out on the east coast of England.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My commute into work in the morning is just over two hours, and my commute home is either the same or worse depending on the state of the trains and the nightmare that is the home time commuting hours of 4pm-7pm. That&amp;rsquo;s almost five hours a day sitting (or more likely standing) on a train.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, because of my locality I have to be up &lt;em&gt;before&lt;/em&gt; 6am in order to get to work by a reasonable hour. It also means, to avoid the commuter rush in the evening (including trying to acquire a seat for that long trip home), I typically have to leave the office by approximately 4.30pm latest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t know about you but I consider that&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;stressful&lt;/li&gt;&#xA;&lt;li&gt;tiring&lt;/li&gt;&#xA;&lt;li&gt;inefficient&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Before I had a family, that would have been time back to myself to do things such as: having a more relaxed breakfast, having more time to get ready for the day ahead and maybe even going to the gym before work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now that I &lt;em&gt;have&lt;/em&gt; a family, that&amp;rsquo;s critical time I get to spend with them before I start work, as well as to do some house chores and help my wife with getting our son ready in the morning.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t have children, then it&amp;rsquo;s probably best that I explicitly state what otherwise might be considered &amp;lsquo;stating the obvious&amp;rsquo; (and apologies if so), but just in case: getting children ready in the morning is a lot harder, time consuming and stressful than you&amp;rsquo;ll probably realise. So it&amp;rsquo;s important I help my wife with this otherwise it&amp;rsquo;s a massive burden on her shoulders.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this can often be something as simple (but meaningful) as looking after our son for a mere &lt;em&gt;ten minutes&lt;/em&gt; just so she can get washed and dressed!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Not to mention things like getting deliveries to your home, or getting a plumber round to fix your sink, or even time to take your kids to the doctors.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All of these things that people have to deal with in their day-to-day lives can be made easier if we were able to work from home.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;problems-with-remote-working&#34;&gt;Problems with Remote Working&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so not everything is roses. Here is a short list of things that can be a concern when working from home (and I&amp;rsquo;ll dig into each afterwards):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When do I start/finish?&lt;/li&gt;&#xA;&lt;li&gt;How do I get noticed/feel included?&lt;/li&gt;&#xA;&lt;li&gt;How can I be impactful?&lt;/li&gt;&#xA;&lt;li&gt;How should I communicate?&lt;/li&gt;&#xA;&lt;li&gt;How do I prove I&amp;rsquo;m getting stuff done?&lt;/li&gt;&#xA;&lt;li&gt;How do I avoid procrastinating?&lt;/li&gt;&#xA;&lt;li&gt;How can I stay healthy?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is a small list from a much larger set of questions people often have about remote working, but hopefully these are enough items for me to discuss to help get across my thoughts.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;when-do-i-start-finish&#34;&gt;When do I start/finish?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is important. You &lt;em&gt;need&lt;/em&gt; a routine. Doesn&amp;rsquo;t matter what it is, but you need one. If you think remote working is waking up whenever you like every day and wandering around the house in your pyjamas and whimsically selecting the code tasks you&amp;rsquo;re going to hack on, then you&amp;rsquo;re in for a rude awakening.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remote working is WORK. So you get up at a consistent time in the morning, you get washed and dressed, you have breakfast and a coffee/tea, and then you think about the day ahead. Start WORK.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is likely going to sound &lt;em&gt;no different&lt;/em&gt; to maybe how you&amp;rsquo;re working at the moment as a &amp;lsquo;non-remote&amp;rsquo; worker, right! Exactly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m up at 7am and I start work by 9am (sometimes 10am if there&amp;rsquo;s something else I need to do in the morning). I do a full day&amp;rsquo;s work: so if I start at 9am I&amp;rsquo;ll be finished by 5pm. If I&amp;rsquo;m starting at 10am I&amp;rsquo;ll work till 6pm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sometimes you&amp;rsquo;ll find a natural wrap up of your day is earlier than when you should &amp;lsquo;officially&amp;rsquo; finish. For example, you&amp;rsquo;re planning to finish at 5pm but it&amp;rsquo;s 4:30 and you don&amp;rsquo;t want to pick up another large task today.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In those instances, I would normally just jump over to read through any late email I&amp;rsquo;ve received. I&amp;rsquo;d then jump onto Slack and check-in with my team, most likely I&amp;rsquo;ll be dropping an &amp;lsquo;end of day summary&amp;rsquo; (which can be very helpful for my team mates who are based in different timezones to me).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-do-i-get-noticed-feel-included&#34;&gt;How do I get noticed/feel included?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is actually a subtle question with many different layers to it. In most companies I work for I start as a &amp;lsquo;partial&amp;rsquo; remote worker (so maybe two days a week in the office). That can be really helpful as far as building up relationships with my colleagues. You &lt;em&gt;need&lt;/em&gt; good relationships.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if you&amp;rsquo;re starting off as a completely 100% remote worker, don&amp;rsquo;t worry, building relationships is easy enough to do. It just takes a bit of effort on your part (which I&amp;rsquo;ll explain next). I can say it&amp;rsquo;s easy to do because I have built up many &lt;em&gt;great&lt;/em&gt; working relationships with my colleagues based in the United States (both in the eastern and western timezones).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although reaching the western timezone is tricker than eastern as it&amp;rsquo;s a solid eight hours behind. It&amp;rsquo;s possible to do still, but again will take just a bit more effort if that&amp;rsquo;s what you want.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Ultimately it comes down to &lt;em&gt;communication&lt;/em&gt; (and &lt;em&gt;good&lt;/em&gt; communication at that). For communication to be considered &amp;lsquo;good&amp;rsquo; it needs to happen at the right time and in the right medium (see &lt;a href=&#34;#how-should-i-communicate&#34;&gt;How should I communicate?&lt;/a&gt; for more details on this subject).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll find that I will, every morning (hopefully around the same time) drop a message into Slack (for the UK engineering team) saying something along the lines of&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Morning all 👋&#xA;&#xA;&amp;lt;funny gif&amp;gt;&#xA;&#xA;_^^ some explanation of the gif_&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I typically put an explanation below the gif if it is based on the current weather outside, or maybe there&amp;rsquo;s a big event happening, or maybe it&amp;rsquo;s just a funny caption to go with the gif, whatever.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I do this is because that&amp;rsquo;s &lt;em&gt;me&lt;/em&gt;. That&amp;rsquo;s the type of person I am and I want other people to recognise that this is my personality coming through. I&amp;rsquo;m giving a bit of &lt;em&gt;myself&lt;/em&gt; to these people. I also then do the same thing for my team (who currently are all based outside of the UK) in our own team Slack channel.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Of course I don&amp;rsquo;t &lt;em&gt;just&lt;/em&gt; do that 😉 I&amp;rsquo;m also very open about my personal life and what I&amp;rsquo;m doing. For example, I&amp;rsquo;ll often post pictures of my daily lunch time walks with my son.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, the reason I do this isn&amp;rsquo;t to gloat (although sometimes it is when the weather is sunny) but a nice coastal scenery shot with me and my son in it, reminds people that I&amp;rsquo;m a human being and not some anonymous entity behind a keyboard and screen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should try to learn more about your colleagues, and appreciate what sorts of things &lt;em&gt;they&amp;rsquo;re&lt;/em&gt; into. Maybe they love photography or are into games or books. Maybe they like riding their bike on the weekend or going rock climbing. Having freeform non-work related conversations is great for this (so find a space to have those conversations).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for example I know a colleague of mine who works in Argentina loves cats and has two of her own. I also have cats and we chat regularly in DM&amp;rsquo;s about not only work, but we share pictures of our cats. Simple things like that help build stronger relationships and makes working together more meaningful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also follow each other on Instagram, and I have many work friends (current and old) who follow me (and vice-versa) on twitter and facebook. We spend a large majority of our life at work, so making friends and really caring about who you work with will make a massive positive impact on your enjoyment while at work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t limit yourself to reaching out to just your team, or to people in your locality. Make an effort to take part in various channels of communication (including those that might be happening across different timezones). This might be as simple as joining various Slack channels where people talk about certain languages or tech, but it can include joining various &amp;lsquo;working groups&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve been part of, and led, many working groups (architecture, code design, documentation, communication). You can spin up a working group about &lt;em&gt;anything&lt;/em&gt; you&amp;rsquo;re interested in and by sharing it with the organization you&amp;rsquo;ll be surprised to discovered that there are likely lots of like-minded individuals interested in the same things and willing to discuss and to want to help improve the quality of the &amp;lsquo;thing&amp;rsquo; happening within the organization.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you start doing the groundwork of understanding your colleagues and proactively sharing a piece of your true self at work, you&amp;rsquo;ll also find that people will start reaching out to you, for both your opinion and to include you in conversations (this could be because they recognize you have specific skills that will benefit their project or maybe it&amp;rsquo;s something more informal &amp;ndash; someone cracked a joke and cc&amp;rsquo;s you as part of it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You have (for lack of a better word) &amp;lsquo;exposed&amp;rsquo; yourself to the organization.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-should-i-communicate&#34;&gt;How should I communicate?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Communication takes many forms and is one of the biggest contributing factors to misunderstanding requirements, and to personal unhappiness. It&amp;rsquo;s one of the most critical skills to learn and to utilize (regardless of whether you&amp;rsquo;re a remote worker or not).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, don&amp;rsquo;t just Slack people all the time. You should notice when conversations are getting out of hand (i.e. too much back and forth overlapping textual messages with no one really &lt;em&gt;reading&lt;/em&gt; the other person&amp;rsquo;s message, you&amp;rsquo;re both firing off in the hope that &lt;em&gt;your&lt;/em&gt; point is heard first) and offer instead to jump over to a &amp;lsquo;face-to-face&amp;rsquo; video call to clarify.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With face-to-face people generally are more easily able to listen because the convention in our society isn&amp;rsquo;t to shout interweavingly across each other. Instead, someone talks and (if you&amp;rsquo;re doing what you&amp;rsquo;re supposed to be) you&amp;rsquo;ll be &lt;em&gt;listening&lt;/em&gt; and really taking in what the other person is saying. You&amp;rsquo;ll then adapt your response based on what the other person has just said †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this is much different to what a lot of people mistakenly do which is: stay quiet until the other person has stopped talking and then reply with their pre-canned response (i.e. again they&amp;rsquo;re only interested in getting across &lt;em&gt;their&lt;/em&gt; own points).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;One thing that I like to do after taking a long Slack conversation into a face-to-face video call is to go back to Slack and to &lt;em&gt;summarize&lt;/em&gt; what was just disussed. There are a few reasons for doing this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;it&amp;rsquo;s a documented record of what was discussed.&lt;/li&gt;&#xA;&lt;li&gt;it confirms that everyone has &lt;em&gt;understood&lt;/em&gt; the outcome correctly.&lt;/li&gt;&#xA;&lt;li&gt;it shows you&amp;rsquo;re conscientious of people in other timezones (who might have been following the conversation).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Another important characteristic of good communication: you should also aim to be &amp;lsquo;clear&amp;rsquo; and, if the situation calls for it, concise (this is something I&amp;rsquo;m guilty of not being good at, but I&amp;rsquo;m aware of that problem and try hard to be better at).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In my blog posts I&amp;rsquo;m definitley not concise, but then I&amp;rsquo;m usually &amp;lsquo;telling a story&amp;rsquo; and that&amp;rsquo;s a different situation to writing an email or a Slack message (but even still I&amp;rsquo;ve a long way to go to improve &amp;ndash; no one&amp;rsquo;s perfect).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For those of you who are interested I would highly recommend reading the following material:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.radicalcandor.com/&#34; target=&#34;_blank&#34;&gt;Radical Candor: care personally and challenge directly&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.nonviolentcommunication.com/&#34; target=&#34;_blank&#34;&gt;Nonviolent Communication&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.soundstrue.com/store/authentic-communication.html&#34; target=&#34;_blank&#34;&gt;Authentic Communication&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A couple of other important notes to make:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Make sure you block out time in your calendar for important events&lt;/strong&gt;, such as a lunch hour or family time etc. This becomes especially useful when working within a distributed company, for example, in my calendar I block out 5pm to 10pm for &amp;lsquo;family time&amp;rsquo; so people in New York and LA can&amp;rsquo;t accidentally try to book a meeting with me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Schedule monthly 1:1 meetings with people of differing levels within the company&lt;/strong&gt;, such as interns, seniors, managers, designers etc. This is useful because it gives you a regular &amp;lsquo;check-in&amp;rsquo; with what&amp;rsquo;s happening elsewhere in the organisation &lt;em&gt;and&lt;/em&gt; it also helps others to get to know &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-can-i-be-impactful&#34;&gt;How can I be impactful?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To have &amp;lsquo;impact&amp;rsquo; can take many different forms. Being impactful isn&amp;rsquo;t &lt;em&gt;just&lt;/em&gt; about getting a job done. It could be mentoring colleagues, or it could be noticing a problem space (either in the tools your organization uses or the services it provides) and producing an RFC documentation that tackles some possible solutions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I think ultimately to be impactful requires you to &lt;em&gt;care&lt;/em&gt;. You need to care about the organization and its success. You need to care about your colleagues and &lt;em&gt;their&lt;/em&gt; success.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re just turning up at work to &amp;lsquo;go through the motions&amp;rsquo; and to just &amp;lsquo;get paid&amp;rsquo;, then you&amp;rsquo;ll likely always fall short of having true life affirming impact.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-do-i-prove-i-m-getting-stuff-done&#34;&gt;How do I prove I’m getting stuff done?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is a classic concern for both people wanting to be a remote worker, as well as organizations who are unsure remote working is something they want to offer to their workers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Any half decent organization is going to have &amp;lsquo;process&amp;rsquo; and that process should be effective regardless of whether you&amp;rsquo;re remote or not. You should have some form of project/task tracker (e.g. Jira), you should have some form of methodology of working (e.g. Kanban, Scrum, Agile etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this process you should have enough to demonstrate you&amp;rsquo;re &amp;lsquo;getting things done&amp;rsquo;. For example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Daily team standups&lt;/strong&gt;: this is your chance to say what you worked on yesterday, what you worked on today, and whether anything is blocking you. This is a great time to express things concerning you and for your manager/team to get an insight into that.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Task tracking&lt;/strong&gt;: if you use Jira then you&amp;rsquo;ll have a set of tasks on a backlog that are prioritized and are assigned to specific individuals. Management can track and review what you&amp;rsquo;re doing and see if things aren&amp;rsquo;t getting done.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;One to one meetings&lt;/strong&gt;: you have an opportunity at 1-1 meetings with your line manager to express your concerns, and it can be a good time to highlight things you&amp;rsquo;re doing (not project/task specific as that&amp;rsquo;s not the point of 1-1&amp;rsquo;s, but maybe you&amp;rsquo;ve created a working group or are working on an important RFC).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;how-do-i-avoid-procrastinating&#34;&gt;How do I avoid procrastinating?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I personally feel that people are capable of procrastinating regardless of whether they&amp;rsquo;re remote or not. To avoid procrastinating means being focused, getting rid of distractions, settings yourself deadlines and generally being organized.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;None of these are traits that should be limited to remote workers, as this is just what it means to be an attentive and considerate worker.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would say that if you&amp;rsquo;re going to be a remote worker though, you&amp;rsquo;ll want to have yourself a space where you can work. Yes it&amp;rsquo;s nice to be able to work from any where in your home, but to have a dedicated &amp;lsquo;office space&amp;rsquo; is important.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have an office space which I use the majority of the time because it&amp;rsquo;s quiet and it&amp;rsquo;s away from the family noise. But I also find that when it&amp;rsquo;s sunny I like to work from the lounge in the morning (because the sun hits that room first, and also means I can be around my son while he&amp;rsquo;s enjoying his morning playtime).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I might then move to working from the kitchen so I can look out at my garden and again enjoy some sunshine and scenery as the sun moves around during the day. But again, I do mainly work from my office space, especially when I have meetings or I feel I really need to concentrate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you listen to music while working then that can actually be a cause of distraction. For me, if I need to focus (or am working on something I&amp;rsquo;m unsure about) I tend to find music with lyrics generally distracts me so I&amp;rsquo;ll listen to genres like jazz, classical or downbeat instrumental (trip hop&amp;rsquo;ish stuff like DJ Crush&amp;rsquo;s &amp;ldquo;Code 4109&amp;rdquo;). But if I&amp;rsquo;m working on a system I know very well and I&amp;rsquo;m just churning out stuff like a batch of unit tests, then I can listen to anything.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately you need to get used to recognizing when you&amp;rsquo;re distracted and to combat that however it makes sense for you.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-can-i-stay-healthy&#34;&gt;How can I stay healthy?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is a very important topic as remote workers are notorious from suffering burnout from over working. You need to have clear boundaries, so you need to say: I start at N time in the morning and I&amp;rsquo;ll finish at N time in the evening. I&amp;rsquo;ll also have lunch at N time during the day (and have a &lt;em&gt;full&lt;/em&gt; lunch).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me personally I have a desk that transitions from a sitting desk to a standing desk. I find in the morning I like to stand for an hour or two and then I&amp;rsquo;ll sit for an hour or two, and then I&amp;rsquo;ll go for a walk along the seafront (sometimes with my son or sometimes by myself if I need some space) during my lunch hour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I make sure that my lunch is something I cook. I avoid &amp;lsquo;ready meals&amp;rsquo; or snacky foods like crisps and chocolates (I generally only ever have a nibble of dark chocolate in the evenings if I have a sugar craving).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As an example, a general day of eating will look something like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Breakfast&lt;/strong&gt;: bowl of mixed nuts, raisins, blackberries, banana, pumpkin seeds and oat milk.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Lunch&lt;/strong&gt;: salmon and salad.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Dinner&lt;/strong&gt;: meat, veg and a bit of carb.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I also don&amp;rsquo;t drink coffee or &amp;lsquo;normal&amp;rsquo; tea. I&amp;rsquo;m primarily a drinker of water, peppermint tea, and if I need caffeine I&amp;rsquo;ll drink a pot of &lt;a href=&#34;https://theguayusa.co/&#34; target=&#34;_blank&#34;&gt;Guayusa&lt;/a&gt; green tea (which has more caffeine than coffee but is much healthier for you).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re able to, try and do some exercise as well! A sedentary lifestyle is not good for us. If you can&amp;rsquo;t get to a gym or aren&amp;rsquo;t motivated to do exercise then don&amp;rsquo;t kick yourself about it. But do get up and out of your chair for a walk every once in a while. Fresh air really does make a world of difference.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The key thing is to be &amp;lsquo;active&amp;rsquo; and to have space to think about &lt;em&gt;other&lt;/em&gt; things that aren&amp;rsquo;t work related as this will actually help your subconscious to really kick-in behind the scenes and process conversations and other things going on at work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also important to realize that you&amp;rsquo;re &lt;em&gt;remote&lt;/em&gt; so you don&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; to work from &amp;lsquo;home&amp;rsquo;. You can work anywhere there&amp;rsquo;s an internet connection (if your work provides you with a mobile wifi then that&amp;rsquo;s even better because you can just go to the beach and work from there if you like).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve never done it but I could imagine going to my local library and working from there to be quite nice. Maybe going to a bustling coffee shop with free wifi? Either way, get out and away from your home as often as you can so you don&amp;rsquo;t start building up a form of &amp;lsquo;cabin fever&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-doesn-t-work-well&#34;&gt;What doesn&amp;rsquo;t work well?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, there are some things that still don&amp;rsquo;t work that great when being a remote. Below is a small selection:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Whiteboard discussions&lt;/strong&gt;: architecture design meetings using a whiteboard can be difficult. there is technology to help with this but it&amp;rsquo;s not great. One thing we&amp;rsquo;re looking to explore is for all employees (remote and in-office) to have access to a drawing tablet for their computer so they can draw with an electronic pen into some shared screen software. This would be much more flexible and easier to work with than trying to draw with a mouse.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Remote meetings&lt;/strong&gt;: specifically I&amp;rsquo;m referring to people who aren&amp;rsquo;t familiar with doing remote meetings and so they&amp;rsquo;ll do silly things like treating the remotes as if they aren&amp;rsquo;t there. So they&amp;rsquo;ll sit with their back to the camera, or they&amp;rsquo;ll ask for opinions from people in the room but not take the time to say: &amp;ldquo;for those here who are attending remotely, does anyone have anything to add?&amp;rdquo; (because jumping into a conversation remotely can be much harder than if you&amp;rsquo;re in a physical office/room).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Unplanned conversations&lt;/strong&gt;: sometimes conversations are sparked in the office between colleagues. They don&amp;rsquo;t always happen on Slack, and so it&amp;rsquo;s important that those people in the office are thinking about their remote colleagues and include them when necessary.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;That said, there&amp;rsquo;s not much that&amp;rsquo;s so problematic that remote working couldn&amp;rsquo;t be a consideration for most organizations.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Hopefully you&amp;rsquo;ve found this rundown of remote working (from someone who has been remote working for many many years now with great success and much learnings under his belt). If you have any additional questions then do please reach out to me on twitter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/remote-working/</guid>
      <link>https://www.integralist.co.uk/posts/remote-working/</link>
      <pubDate>Sat, 09 Mar 2019 00:00:00 +0000</pubDate>
      <title>Remote Working</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Mocking resources when writing tests in Python can be confusing if you&amp;rsquo;re unfamiliar with doing such things. In this post I am going to cover various aspects of mocking code, which will hopefully be a useful resource for those who are a bit stuck.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the code examples I&amp;rsquo;m using &lt;a href=&#34;https://docs.pytest.org/en/latest/&#34; target=&#34;_blank&#34;&gt;pytest&lt;/a&gt;, but for the most part that shouldn&amp;rsquo;t matter.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;unittest-mock-or-mock&#34;&gt;unittest.mock or mock&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order to &amp;lsquo;mock&amp;rsquo; a resource we&amp;rsquo;ll first need the &lt;code&gt;mock&lt;/code&gt; module, and this is our first stumbling block: which version do we need? i.e. there&amp;rsquo;s two and they both look to be &lt;em&gt;official&lt;/em&gt; (&lt;code&gt;mock&lt;/code&gt; and &lt;code&gt;unittest.mock&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;mock&lt;/code&gt; module is a backwards compatible library you can download from PyPy, where as &lt;code&gt;unittest.mock&lt;/code&gt; is the same thing but only compatible with the version of Python you&amp;rsquo;re using.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in almost all cases you&amp;rsquo;ll want to import it like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import unittest.mock as mock&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For more examples, see &lt;a href=&#34;http://www.voidspace.org.uk/python/mock/examples.html&#34; target=&#34;_blank&#34;&gt;this reference guide&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;decorator&#34;&gt;Decorator&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The most common way to mock resources is to use a Python decorator around your test function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&amp;quot;thing&amp;quot;)&#xA;def test_stuff(mock_thing):&#xA;    mock_thing.return_value = 123&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this case, what we&amp;rsquo;re patching (&lt;code&gt;thing&lt;/code&gt;) can be a variable or a function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you do this you&amp;rsquo;ll need to pass an argument to your function (you can name it whatever you want †) which will be a &lt;a href=&#34;https://docs.python.org/3.7/library/unittest.mock.html#unittest.mock.MagicMock&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;MagicMock&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means if you don&amp;rsquo;t do anything else, then calls to &lt;code&gt;thing&lt;/code&gt; will (in the example above at least) result in the value &lt;code&gt;123&lt;/code&gt; being returned.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† convention is to name the variable &lt;code&gt;mock_&amp;lt;noun&amp;gt;&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re mocking multiple things then you&amp;rsquo;ll stack the mock decorators ontop of each other, and pass them along in order to the test function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&amp;quot;third&amp;quot;)&#xA;@mock.patch(&amp;quot;second&amp;quot;)&#xA;@mock.patch(&amp;quot;first&amp;quot;)&#xA;def test_stuff(mock_first, mock_second, mock_third):&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;resource-location&#34;&gt;Resource location&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to know that when mocking you should specify the location of the resource to be mocked, relevant to where it&amp;rsquo;s &lt;em&gt;imported&lt;/em&gt;. This is best explained by way of example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine I have a module &lt;code&gt;app.foo&lt;/code&gt; and within that module I import another dependency like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from app.bar import thing&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You might think that when you call &lt;code&gt;mock.patch&lt;/code&gt; that you pass it a reference to the resource like &lt;code&gt;app.bar.thing&lt;/code&gt;. That would only be relevant if the resource was being called with that full path within the &lt;code&gt;app.foo&lt;/code&gt; module (e.g. if &lt;code&gt;app.foo&lt;/code&gt; called &lt;code&gt;app.bar.thing(...)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the full namespace path isn&amp;rsquo;t referenced, which it isn&amp;rsquo;t in the above example (notice we import just the &lt;code&gt;thing&lt;/code&gt; resource). It means we need to specify the reference namespace to mock as where it&amp;rsquo;s imported:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;app.foo.thing&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So even though &lt;code&gt;thing&lt;/code&gt; exists within &lt;code&gt;app.bar&lt;/code&gt; we specify &lt;code&gt;app.foo.thing&lt;/code&gt; as &lt;code&gt;app.foo&lt;/code&gt; is where we&amp;rsquo;ve imported it for use. This catches people out all the time.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-return-value-vs-side-effect&#34;&gt;Mock return_value vs side_effect&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If your function has a try/except around it, then you can use &lt;code&gt;side_effect&lt;/code&gt; to cause the calling of the function to trigger an Exception as the returned value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;app.aws.sdk.confirm_sign_up&#39;, side_effect=Exception(&#39;whoops&#39;))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you had used &lt;code&gt;return_value=Exception(&#39;whoops&#39;)&lt;/code&gt; then the mock would return the string representation of the Exception rather than &lt;em&gt;raising&lt;/em&gt; an exception like &lt;code&gt;side_effect&lt;/code&gt; does.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Otherwise if you just need a &lt;em&gt;static&lt;/em&gt; value returned, so it&amp;rsquo;s evaluated at the time it&amp;rsquo;s defined (not when it&amp;rsquo;s called), then you can use &lt;code&gt;return_value&lt;/code&gt; instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;app.security.secret_hash&#39;, return_value=&#39;###&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-nested-calls&#34;&gt;Mock Nested Calls&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Calling a property on a mock returns another mock, so in order to mock very specific properties you&amp;rsquo;ll need to nest your &lt;code&gt;return_value&lt;/code&gt; or &lt;code&gt;side_effect&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;m = mock.MagicMock()&#xA;m.return_value.get.side_effect = [1, 2]&#xA;m.return_value.post.return_value = &#39;foo&#39;&#xA;&#xA;x = m()&#xA;&#xA;x.get()   # 1&#xA;x.post()  # foo&#xA;x.get()   # 2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Things can get a little more confusing when you want to verify a specific nested method on a mocked object was called:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import unittest.mock as mock&#xA;&#xA;from tornado.ioloop import IOLoop&#xA;&#xA;@mock.patch(&amp;quot;__main__.IOLoop&amp;quot;)&#xA;def foo(mock_ioloop):&#xA;    IOLoop.current()&#xA;    mock_ioloop.current.assert_called()  # will fail if assertion isn&#39;t True&#xA;&#xA;    IOLoop.current().start()&#xA;    mock_ioloop.current().start.assert_called()  # will fail if assertion isn&#39;t True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason this can get more complicated is due to how a mock will return a new mock when accessing a property on a mock:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import unittest.mock as mock&#xA;&#xA;from tornado.httpserver import HTTPServer&#xA;&#xA;@mock.patch(&amp;quot;__main__.HTTPServer&amp;quot;)&#xA;def bar(mock_httpserver):&#xA;    server = HTTPServer()&#xA;&#xA;    server.listen(8080)&#xA;    HTTPServer().listen(123)&#xA;&#xA;    mock_httpserver.assert_called()&#xA;    mock_httpserver().listen.assert_called_with(8080)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code will error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;AssertionError: expected call not found.&#xA;Expected: listen(8080)&#xA;Actual: listen(123)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll need to make sure you assert the mock at the right time:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import unittest.mock as mock&#xA;&#xA;from tornado.httpserver import HTTPServer&#xA;&#xA;@mock.patch(&amp;quot;__main__.HTTPServer&amp;quot;)&#xA;def bar(mock_httpserver):&#xA;    server = HTTPServer()&#xA;    mock_httpserver.assert_called()&#xA;    &#xA;    server.listen(8080)&#xA;    mock_httpserver().listen.assert_called_with(8080)&#xA;    &#xA;    HTTPServer().listen(123)&#xA;    mock_httpserver().listen.assert_called_with(123)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;verify-exceptions&#34;&gt;Verify Exceptions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If we want to verify that some piece of code throws an &lt;code&gt;Exception&lt;/code&gt; type when we need it to we can mock specific resources to throw an exception and then use &lt;code&gt;pytest.raises&lt;/code&gt; as a context manager around the caller of our code to be verified.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example our code (in &lt;code&gt;app.account.confirm(...)&lt;/code&gt;) catches a generic &lt;code&gt;Exception&lt;/code&gt; and re-raises it as &lt;code&gt;exceptions.CognitoException&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can catch and make assertions against this expected behaviour by first mocking the resource we want to throw an exception and get it to throw our own fake exception using the &lt;code&gt;side_effect&lt;/code&gt; parameter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we specify the exact exception type we&amp;rsquo;re expecting to be raised using &lt;code&gt;pytest.raises(T)&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;app.aws.sdk.confirm_sign_up&#39;, side_effect=Exception(&#39;whoops&#39;))&#xA;def test_account_confirm_failure(mock_signup):&#xA;    with pytest.raises(exceptions.CognitoException) as exc_info:&#xA;        app.account.confirm(123, &#39;foo&#39;)&#xA;        assert True is True  # this will never be executed!&#xA;        &#xA;    assert exc_info.typename == &#39;CognitoException&#39;&#xA;    assert str(exc_info.value) == &#39;SIGNUP_CONFIRMATION_FAILED&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t make the mistake of putting any assertions within the &lt;code&gt;with&lt;/code&gt; context manager. Once the Exception is raised by the function being called within the &lt;code&gt;with&lt;/code&gt; context manager, all code after it inside the block is skipped.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;clearing-lru-cache&#34;&gt;Clearing lru_cache&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If a function you wish to test has the &lt;code&gt;functools.lru_cache&lt;/code&gt; decorator applied, then you&amp;rsquo;ll need to be mindful of mocking the response of that function as it&amp;rsquo;ll be cached in one test and the cached result will be returned when calling the function again to test some other behaviour (and might likely confuse you when you see the unexpected response).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To fix this issue is very easy because &lt;code&gt;lru_cache&lt;/code&gt; provides additional functions when decoratoring your functions, it provides:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cache_info&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cache_clear&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The latter (&lt;code&gt;cache_clear&lt;/code&gt;) is what you would need to call. This is demonstrated below:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@lru_cache(5)&#xA;def foo():&#xA;    print(&#39;Executing foo...&#39;)&#xA;    &#xA;foo()  # Executing foo...&#xA;foo()  # &amp;lt;nothing printed as None response was cached and returned&amp;gt;&#xA;foo.cache_info()  # CacheInfo(hits=1, misses=1, maxsize=5, currsize=1)&#xA;foo.cache_clear()&#xA;foo()  # Executing foo... (notice the &#39;side effect of print is executed again)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;debugging this isn&amp;rsquo;t always obvious. Later on I demonstrate how to &lt;a href=&#34;#mock-builtin-open-function&#34;&gt;mock the builtin &lt;code&gt;open&lt;/code&gt; function&lt;/a&gt;, and in that scenario I stumbled across this issue, because although I wasn&amp;rsquo;t mocking the top level function itself (I was mocking the call to &lt;code&gt;open&lt;/code&gt; within), the contents of the file being opened was what was returned and being cached.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-module-level-global-variables&#34;&gt;Mock Module Level/Global Variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With a module variable you can can either set the value directly or use &lt;code&gt;mock.patch&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example we have the variable &lt;code&gt;client_id&lt;/code&gt; which is a global variable inside the &lt;code&gt;app.aws&lt;/code&gt; module which we import to reference elsewhere in our code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import app.aws&#xA;&#xA;&#xA;def test_account_confirm_successful():&#xA;    app.aws.client_id = 456  # used internally by `confirm()`&#xA;    ...&#xA;    &#xA;@mock.patch(&#39;app.aws.client_id&#39;, 456)&#xA;def test_account_confirm_successful():&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the &lt;code&gt;mock.patch&lt;/code&gt; example, there are two key things to notice:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;we don&amp;rsquo;t use &lt;code&gt;return_value&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;there is no mock instance passed to the test function.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;This is because we&amp;rsquo;re modifying a variable and not a direct function or &amp;lsquo;callable&amp;rsquo; so there&amp;rsquo;s no need to pass a mock into the test function (if you want to change the value a few times within the test itself then you would mock the variable but not immediately assign a value in the decorator).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-instance-method&#34;&gt;Mock Instance Method&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are multiple ways to achieve mocking of an instance method. One common approach is to use &lt;code&gt;mock.patch.object&lt;/code&gt;, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from unittest import mock&#xA;&#xA;def test_foo():&#xA;    with mock.patch.object(FooClass, &#39;method_of_class&#39;, return_value=None) as mock_method:&#xA;        instance = SomeClass()&#xA;        instance.method_of_class(&#39;arg&#39;)&#xA;        mock_method.assert_called_with(&#39;arg&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another approach is to mock the method like you would a normal function, but you reference the method via the classname:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def test_bar():&#xA;    r = mock.Mock()&#xA;    r.content = b&#39;{&amp;quot;success&amp;quot;: true}&#39;&#xA;&#xA;    with mock.patch(&#39;requests.get&#39;, return_value=r) as get:  # Avoid doing actual GET request&#xA;        some_function()  # internally calls requests.get&#xA;        get.assert_called_once()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another (although more heavy handed) approach for mocking a class instance method is to take advantage of the fact that a Mock will return a new mock instance when called:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&amp;quot;foo.bar.SomeClass&amp;quot;)&#xA;def test_stuff(mock_class):&#xA;    mock_class.return_value.made_up_function.return_value = &amp;quot;123&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the above example we mock the &lt;em&gt;entire&lt;/em&gt; class, which might not be what you want. If not, then use the previous &lt;code&gt;mock.patch.object&lt;/code&gt; example instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason the above example works is because we&amp;rsquo;re setting &lt;code&gt;return_value&lt;/code&gt; on our mock. Because this is a &lt;code&gt;MagicMock&lt;/code&gt; every attribute referenced returns a new mock instance (a function or property you call on a mock doesn&amp;rsquo;t have to exist) and so we call &lt;code&gt;made_up_function&lt;/code&gt; on the returned mock, and on &lt;em&gt;that&lt;/em&gt; newly created mock we set the final &lt;code&gt;return_value&lt;/code&gt; to &lt;code&gt;123&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But as mentioned in the above note, this approach might be a little &lt;em&gt;too&lt;/em&gt; blunt depending on what your needs are (whether you care whether you have a some what functioning class or not).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-class-method&#34;&gt;Mock Class Method&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To mock a class method is a similar approach to mocking an instance method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One approach might be that you mock the entire class (but now you have one less &lt;code&gt;return_value&lt;/code&gt; to assign to):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;mock_class.ClassMethodName.return_value = &amp;quot;123&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Or better yet you should mock it like you would any normal function, but just reference the method via the class:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;myapp.Foo.class_method_name&#39;)&#xA;def test_classmethod(self, mock_class_method):&#xA;    mock_class_method.return_value = &amp;quot;foobar&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-entire-class&#34;&gt;Mock Entire Class&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To mock an entire class you&amp;rsquo;ll need to set the &lt;code&gt;return_value&lt;/code&gt; to be a new instance of the class.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;myapp.app.Car&#39;)&#xA;def test_class(self, mock_car):&#xA;&#xA;    class NewCar(object):&#xA;        def get_make(self):&#xA;            return &#39;Audi&#39;&#xA;&#xA;        @property&#xA;        def wheels(self):&#xA;            return 6&#xA;&#xA;    mock_car.return_value = NewCar()&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See other class related mocking tips &lt;a href=&#34;https://chase-seibert.github.io/blog/2015/06/25/python-mocking-cookbook.html&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-async-calls&#34;&gt;Mock Async Calls&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Mocking asynchronous code is probably the most confusing aspect of mocking. My &amp;lsquo;go to&amp;rsquo; solution I&amp;rsquo;ll explain first, but after that I&amp;rsquo;ll share some alternative methods I&amp;rsquo;ve seen and tried in the past.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First consider this asynchronous code inside of a &lt;code&gt;app.foo&lt;/code&gt; module:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import app.stuff&#xA;&#xA;async def do_thing(x):&#xA;  return await app.stuff.some_concurrent_function(x)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we need to mock the coroutine &lt;code&gt;app.stuff.some_concurrent_function&lt;/code&gt;, then we can solve this by creating a function that acts as a &lt;a href=&#34;https://docs.python.org/3.7/library/asyncio-task.html#asyncio.coroutine&#34; target=&#34;_blank&#34;&gt;coroutine&lt;/a&gt; and allow it to be configurable for different types of responses:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the example uses &lt;a href=&#34;https://www.tornadoweb.org/en/stable/&#34; target=&#34;_blank&#34;&gt;tornado&lt;/a&gt; for running an asynchronous test.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def make_coroutine(response):&#xA;    &amp;quot;&amp;quot;&amp;quot;You could pass response as a mock or a raw data structure, doesn&#39;t matter.&amp;quot;&amp;quot;&amp;quot;&#xA;    &#xA;    async def coroutine(*args, **kwargs):&#xA;        &amp;quot;&amp;quot;&amp;quot;*args will be whatever is passed to the original async function.&#xA;        &#xA;        Meaning you could have a conditional check that let&#39;s us change &#xA;        the response to be anything we need.&#xA;        &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;        return response&#xA;&#xA;    return coroutine&#xA;&#xA;class TestThing(tornado.testing.AsyncTestCase):&#xA;    @mock.patch(&#39;app.stuff.some_concurrent_function&#39;)&#xA;    @tornado.testing.gen_test&#xA;    def test_async_func(self, mock_thing):&#xA;        mock_thing.side_effect = make_coroutine(&#39;some response&#39;)&#xA;        result = yield app.foo.do_thing(&#39;xyz&#39;)&#xA;        assert result == &#39;some response&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you do include an &lt;code&gt;if&lt;/code&gt; statement within &lt;code&gt;make_coroutine&lt;/code&gt;, you could pass in a MagicMock as a simple way of having a single input give you multiple different values back&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def make_coroutine(response):&#xA;    async def coroutine(*args, **kwargs):&#xA;        if args[0] == &#39;x&#39;:&#xA;            return response.x&#xA;        elif args[0] == &#39;y&#39;:&#xA;            return response.y&#xA;        else:&#xA;            return response.default&#xA;&#xA;    return coroutine&#xA;&#xA;m = mock.MagicMock(x=1, y=2, default=3)&#xA;coro = make_coroutine(m)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When dealing with side_effects that need to sometimes trigger an Exception and other times suceed you could use a slightly modified mock implementation that checks if the given response object is callable or not&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;count = 0&#xA;&#xA;def make_side_effect_coroutine(side_effect):&#xA;    &amp;quot;&amp;quot;&amp;quot;Side effect friendly mock coroutine.&#xA;&#xA;    In some tests we need to have a mocked coroutine return a different value&#xA;    when it&#39;s called multiple times, but a mock side_effect can&#39;t trigger a&#xA;    raised exception when given an iterator, and so we have to construct that&#xA;    behaviour ourselves.&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    async def coroutine(*args, **kwargs):&#xA;        return side_effect(*args, **kwargs) if callable(side_effect) else side_effect&#xA;    return coroutine&#xA;    &#xA;@mock.patch(&#39;app.thing&#39;)&#xA;def test_confirm_email_change_failure(self, mock_thing):&#xA;&#xA;    def side_effects(*args, **kwargs):&#xA;        &amp;quot;&amp;quot;&amp;quot;Use global var to control mock side effects.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;        global count&#xA;&#xA;        if count &amp;gt; 0:&#xA;            raise Exception(&#39;whoops&#39;)&#xA;&#xA;        count += 1&#xA;        return  # don&#39;t raise an exception the first time around&#xA;&#xA;    mock_thing.side_effect = make_side_effect_coroutine(side_effects)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If the above approach doesn&amp;rsquo;t work for you, here are some alternatives&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;asyncmock&#34;&gt;AsyncMock&lt;/h3&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this utilizes the package &lt;code&gt;pytest-asyncio&lt;/code&gt; to help with testing asyncio code&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start with the code to be mocked&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import asyncio&#xA;&#xA;async def sum(x, y):&#xA;    await asyncio.sleep(1)&#xA;    return x + y&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now here&amp;rsquo;s how we&amp;rsquo;d mock it&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import pytest&#xA;import asyncio&#xA;&#xA;# create a new pytest fixture called mock_sum&#xA;#&#xA;@pytest.fixture()&#xA;def mock_sum(mocker):&#xA;    async_mock = AsyncMock()&#xA;    mocker.patch(&#39;app.sum&#39;, side_effect=async_mock)&#xA;    return async_mock&#xA;&#xA;    # Python &amp;lt;3.8 would have used&#xA;    #&#xA;    # future = asyncio.Future()&#xA;    # mocker.patch(&#39;app.sum&#39;, return_value=future)&#xA;    # return future&#xA;&#xA;@pytest.mark.asyncio&#xA;async def test_sum(mock_sum):&#xA;    mock_sum.return_value = 4&#xA;&#xA;    # Python &amp;lt;3.8 would have used&#xA;    #&#xA;    # mock_sum.set_result(4)&#xA;&#xA;    result = await sum(1, 2)&#xA;    assert result == 4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;monkey-patch&#34;&gt;Monkey Patch&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# allow mock to be used as an await expression...&#xA;&#xA;async def async_response():&#xA;    return namedtuple(&#39;_&#39;, [&#39;body&#39;])(&#39;{&amp;quot;state&amp;quot;: &amp;quot;success&amp;quot;}&#39;)&#xA;&#xA;&#xA;def mock_async_expression(our_mock):&#xA;    return async_response().__await__()&#xA;&#xA;&#xA;mock.MagicMock.__await__ = mock_async_expression&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;magicmock-subclass&#34;&gt;MagicMock Subclass&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class AsyncMock(MagicMock):&#xA;    async def __call__(self, *args, **kwargs):&#xA;        return super(AsyncMock, self).__call__(*args, **kwargs)&#xA;        &#xA;class TestHandlers(testing.AsyncTestCase):&#xA;    @mock.patch(&#39;app.handlers.trigger_soft_cdn_purge&#39;, new_callable=AsyncMock)&#xA;    @mock.patch(&#39;app.handlers.api&#39;)&#xA;    @testing.gen_test&#xA;    async def test_update_cache(self, api_mock, trigger_soft_cdn_purge):&#xA;        response = mock.MagicMock()&#xA;        response.code = 200&#xA;        api_mock.buzz = AsyncMock(return_value=response)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;async-inline-function&#34;&gt;Async Inline Function&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@mock.patch(&#39;app.buzz_api.api_gateway&#39;)&#xA;@testing.gen_test&#xA;async def test_buzz_api(self, client_mock):&#xA;    async def get(url, **kwargs):&#xA;        return&#xA;        &#xA;    client_mock.get.side_effect = get&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-instance-types&#34;&gt;Mock Instance Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When mocking an object you&amp;rsquo;ll find that the mock replaces the entire object and so it can cause tests to pass (or fail) in unexpected ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning, if you need to make a mock more like the concrete interface, then there are two ways to do that:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;spec&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;wrap&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;We can use mock&amp;rsquo;s &lt;code&gt;spec&lt;/code&gt; feature to mimic all methods/attributes of the object being mocked. This ensures your mocks have the same api as the objects they are replacing.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is a stricter &lt;code&gt;spec_set&lt;/code&gt; that will raise an &lt;code&gt;AttributeError&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This is best demonstrated with an example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import unittest.mock as mock&#xA;import tornado.simple_httpclient&#xA;&#xA;from tornado.httpclient import AsyncHTTPClient&#xA;&#xA;&#xA;http_client = AsyncHTTPClient()&#xA;type(http_client)  # tornado.simple_httpclient.SimpleAsyncHTTPClient&#xA;&#xA;isinstance(http_client, tornado.simple_httpclient.SimpleAsyncHTTPClient)  # True&#xA;&#xA;isinstance(mock.MagicMock(), tornado.simple_httpclient.SimpleAsyncHTTPClient)  # False&#xA;&#xA;m = mock.MagicMock(spec=tornado.simple_httpclient.SimpleAsyncHTTPClient)&#xA;isinstance(m, tornado.simple_httpclient.SimpleAsyncHTTPClient)  # True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;wrap&lt;/code&gt; parameter on the other hand allows you to &amp;lsquo;spy&amp;rsquo; on the implementation, as well as affect its behaviour. In the following example I want to spy on the builtin &lt;code&gt;datetime&lt;/code&gt; implementation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@pytest.mark.parametrize(&amp;quot;input_date, input_url, valid&amp;quot;, [&#xA;    (&amp;quot;2017-06-17T00:00:00.000000Z&amp;quot;, &amp;quot;foo&amp;quot;, True),&#xA;    (&amp;quot;2017-06-18T00:00:00.000000Z&amp;quot;, &amp;quot;bar&amp;quot;, False),&#xA;])&#xA;@mock.patch(&amp;quot;app.handlers.data.datetime&amp;quot;, wraps=datetime)&#xA;def test_valid_video(mock_datetime, input_date, input_url, valid):&#xA;    mock_datetime.now.return_value = datetime(2017, 6, 18, 00, 00, 00, 000000)&#xA;    assert valid_video(input_date, input_url) is valid&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another way to use &lt;code&gt;wrap&lt;/code&gt; is like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from unittest import mock&#xA;&#xA;&#xA;class Foo(object):&#xA;    def bar(self, x, y):&#xA;        return x + y + 1&#xA;&#xA;def test_bar():&#xA;    foo = Foo()&#xA;    with mock.patch.object(foo, &#39;bar&#39;, wraps=foo.bar) as wrapped_foo:&#xA;        foo.bar(1, 3)&#xA;        wrapped_foo.assert_called_with(1, 2)&#xA;&#xA;test_bar()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another simplified version of the above that mocks the whole object, not just a single method:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from unittest import mock&#xA;&#xA;class Foo():&#xA;    def bar(self, msg):&#xA;        print(msg)&#xA;&#xA;f = Foo()&#xA;spy = mock.MagicMock(wraps=f)&#xA;&#xA;spy.bar(&#39;baz&#39;)&#xA;spy.bar.assert_called_with(&#39;beep&#39;)  # raises AssertionError&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;mock-builtin-open-function&#34;&gt;Mock builtin &lt;code&gt;open&lt;/code&gt; function&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Python&amp;rsquo;s mock library provides an abstraction for mocking the builtin &lt;code&gt;open&lt;/code&gt; function a lot simpler&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def test_load_ui_messages_successful():&#xA;    &amp;quot;&amp;quot;&amp;quot;Verify ui message YAML file can be read properly.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    file_content = &#39;foo: bar&#39;&#xA;&#xA;    with mock.patch(&#39;bf_auth.utility.open&#39;, mock.mock_open(read_data=file_content), create=True) as mock_builtin_open:&#xA;        assert utils.load_ui_messages(&#39;./path/to/non/existing/file.yaml&#39;) == {&#39;foo&#39;: &#39;bar&#39;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;create=True&lt;/code&gt; param set on &lt;code&gt;mock.patch&lt;/code&gt; means that the &lt;code&gt;mock.MagicMock&lt;/code&gt; returned will automagically create any attributes that are called on the mock (this is because the &lt;code&gt;open&lt;/code&gt; function will attempt to access lots of different things and it&amp;rsquo;s easier for mock to mock out all of that for you).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There we&amp;rsquo;ll end. Hopefully this list of mocking techniques will be able to see you through even the most complex of code needing to be tested. Let me know what you think on twitter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-mocking/</guid>
      <link>https://www.integralist.co.uk/posts/python-mocking/</link>
      <pubDate>Fri, 08 Mar 2019 00:00:00 +0000</pubDate>
      <title>Mocking in Python</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post includes a condensed version of the information gleened from the excellent &lt;a href=&#34;http://interactivepython.org/runestone/static/pythonds/AlgorithmAnalysis/BigONotation.html&#34; target=&#34;_blank&#34;&gt;interactivepython.org&lt;/a&gt; section on algorithm analysis. I strongly recommend you read that if you require more detailed information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The purpose of this post is simply to restructure and simplify the principles offered so I can use it as a quick reference for future practice.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;algorithm&#34;&gt;Algorithm&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-py&#34;&gt;def sumOfN(n):&#xA;   theSum = 0&#xA;   for i in range(1,n+1):&#xA;       theSum = theSum + i&#xA;&#xA;   return theSum&#xA;&#xA;print(sumOfN(10))  # 55&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;analysis-steps&#34;&gt;Analysis Steps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You want to quantify the number of operations (or &amp;lsquo;steps&amp;rsquo;) in the algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Identify the basic unit of computation.&lt;/li&gt;&#xA;&lt;li&gt;Track any operational constants (e.g. &lt;code&gt;theSum = 0&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Track repeatable operations (e.g. &lt;code&gt;theSum = theSum + i&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Identify the most &amp;lsquo;dominant&amp;rsquo; portion.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;explanation&#34;&gt;Explanation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Think about our algorithm &lt;code&gt;sumOfN&lt;/code&gt;: we have &lt;code&gt;n&lt;/code&gt; number of items and we&amp;rsquo;re concerned about the time complexity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we decide the basic unit of computation is variable assignment, then the formula we would use to express this is &lt;code&gt;T(1+n)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If &lt;code&gt;T(1+n)&lt;/code&gt; is the &amp;lsquo;size of the problem&amp;rsquo;, then using &lt;code&gt;sumOfN&lt;/code&gt; as our algorithm, we can evaluate it to mean&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;T(1+n) == 1+n steps&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;1&lt;/code&gt; is a constant (i.e. &lt;code&gt;theSum = 0&lt;/code&gt; happens only once), and &lt;code&gt;n&lt;/code&gt; is the number of iterations we carry out where a single assignment is made (i.e. &lt;code&gt;theSum = theSum + i&lt;/code&gt;) within the &lt;code&gt;sumOfN&lt;/code&gt; function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A critical part of understanding time complexity is that as the problem gets larger, a portion of &lt;code&gt;T(1+n)&lt;/code&gt; is likely to overpower the rest and this is where we use the syntax &lt;code&gt;f(...)&lt;/code&gt; to represent that portion of the algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of &lt;code&gt;T(1+n)&lt;/code&gt; we could say the dominant part is &lt;code&gt;f(n)&lt;/code&gt;, and is also referred to as being &amp;lsquo;the order of magnitude&amp;rsquo; (which is what the &amp;lsquo;O&amp;rsquo; in Big-O stands for).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&amp;lsquo;order of magnitude&amp;rsquo; describes the part of &lt;code&gt;T(n)&lt;/code&gt; that increases the &lt;em&gt;fastest&lt;/em&gt; as &lt;code&gt;n&lt;/code&gt; increases.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can represent the order of magnitude in &amp;lsquo;Big-O&amp;rsquo; syntax like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(f(n))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;f(n) == dominant part of T(n)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Typically we&amp;rsquo;ll not include the &lt;code&gt;f(...)&lt;/code&gt; part of the syntax when using Big-O though. So instead of &lt;code&gt;O(f(n))&lt;/code&gt; we&amp;rsquo;ll just say &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;significant-or-insignificant&#34;&gt;Significant or Insignificant?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As &lt;code&gt;n&lt;/code&gt; gets larger, continuing to use &lt;code&gt;T(n) = 1+n&lt;/code&gt; as our example, the &amp;lsquo;constant&amp;rsquo; &lt;code&gt;1&lt;/code&gt; (i.e. the computation that happened once: &lt;code&gt;theSum = 0&lt;/code&gt;) becomes less and less significant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning we can drop &lt;code&gt;1&lt;/code&gt; from our syntax, resulting in just &lt;code&gt;O(n)&lt;/code&gt; instead of &lt;code&gt;O(1+n)&lt;/code&gt;, and our approximation is just as accurate without it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To clarify this further, I&amp;rsquo;m going to paste verbatim the interactivepython description, as I feel they explain this very well&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;As another example, suppose that for some algorithm, the exact number of steps is &lt;code&gt;T(n) = 5n2 + 27n + 1005&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When &lt;code&gt;n&lt;/code&gt; is small, say &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt;, the constant &lt;code&gt;1005&lt;/code&gt; seems to be the dominant part of the function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However, as &lt;code&gt;n&lt;/code&gt; gets larger, the &lt;code&gt;n2&lt;/code&gt; term becomes the most important.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In fact, when &lt;code&gt;n&lt;/code&gt; is really large, the other two terms become insignificant in the role that they play in determining the final result.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, to approximate &lt;code&gt;T(n)&lt;/code&gt; as &lt;code&gt;n&lt;/code&gt; gets large, we can ignore the other terms and focus on &lt;code&gt;5n2&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In addition, the coefficient &lt;code&gt;5&lt;/code&gt; becomes insignificant as &lt;code&gt;n&lt;/code&gt; gets large.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We would say then that the function &lt;code&gt;T(n)&lt;/code&gt; has an order of magnitude &lt;code&gt;f(n) = n2&lt;/code&gt;, or simply that it is &lt;code&gt;O(n2)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;example-analysis&#34;&gt;Example Analysis&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-py&#34;&gt;a = 5&#xA;b = 6&#xA;c = 10&#xA;&#xA;for i in range(n):&#xA;   for j in range(n):&#xA;      x = i * i&#xA;      y = j * j&#xA;      z = i * j&#xA;&#xA;for k in range(n):&#xA;   w = a*k + 45&#xA;   v = b*b&#xA;&#xA;d = 33&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above code can be calculated as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;T(n) == 3 + 3n2 + 2n + 1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which can be condensed slightly, by combining the singular constants, to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;T(n) == 3n2 + 2n + 4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The constants &lt;code&gt;3&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; are the top level variable assignments: &lt;code&gt;a=5&lt;/code&gt;, &lt;code&gt;b=6&lt;/code&gt;, &lt;code&gt;c=10&lt;/code&gt; and &lt;code&gt;d=33&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;3n2&lt;/code&gt; is because there are three constant variable assignments (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt;, hence the &lt;code&gt;3&lt;/code&gt; in &lt;code&gt;3n2&lt;/code&gt;) that are occurring within the first set of &lt;code&gt;for&lt;/code&gt; statements. The top level &lt;code&gt;for&lt;/code&gt; statement iterates over &lt;code&gt;n&lt;/code&gt; items, and then does so &lt;em&gt;again&lt;/em&gt; hence the &lt;code&gt;n2&lt;/code&gt; portion of &lt;code&gt;3n2&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;2n&lt;/code&gt; is because there are two constant assignments (&lt;code&gt;w&lt;/code&gt; and &lt;code&gt;v&lt;/code&gt;) and they happen &lt;code&gt;n&lt;/code&gt; times due to the last &lt;code&gt;for&lt;/code&gt; statement iterating over &lt;code&gt;n&lt;/code&gt; items.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this in mind we can say the code is &lt;code&gt;O(n2)&lt;/code&gt; because when we look at the exponents of each segment of the time analysis (i.e. the condensed version: &lt;code&gt;3n2 + 2n + 4&lt;/code&gt;) we can see that as &lt;code&gt;n&lt;/code&gt; grows, the &lt;code&gt;n2&lt;/code&gt; portion is the most significant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think about it: looping over &lt;code&gt;n&lt;/code&gt; items and making two assignments within each iteration (which is the &lt;code&gt;2n&lt;/code&gt;) is definitely less complexity than looping over &lt;code&gt;n&lt;/code&gt; items &lt;em&gt;twice&lt;/em&gt; and within each iteration making three assignments (which is the &lt;code&gt;3n2&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Remember: although we write &amp;lsquo;Big-O&amp;rsquo; as &lt;code&gt;O(...)&lt;/code&gt; the underlying principle is &lt;code&gt;O(f(...))&lt;/code&gt;, where &lt;code&gt;f(...)&lt;/code&gt; is the dominant part of &lt;code&gt;T(...)&lt;/code&gt; and when focusing in on the dominant part of the time complexity we drop the constants &amp;ndash; also known as the &lt;em&gt;coefficient&lt;/em&gt; &amp;ndash; (e.g. &lt;code&gt;3n2&lt;/code&gt; thus becomes &lt;code&gt;n2&lt;/code&gt;). This is because the constants become &lt;em&gt;insignificant&lt;/em&gt; as &lt;code&gt;n&lt;/code&gt; grows.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;when-is-big-o-not-relevant&#34;&gt;When is Big-O not relevant?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I recently asked in a computer science forum for help in understanding what the Big-O time complexity would be for a &amp;lsquo;web crawler&amp;rsquo;. Specifically I was asking in relation to the following crawler implementation I had built: &lt;a href=&#34;https://github.com/integralist/go-web-crawler&#34; target=&#34;_blank&#34;&gt;go-web-crawler&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The architecture of the program looks something like this:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/go-web-crawler.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/go-web-crawler.png&#34; alt=&#34;go web crawler&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wasn&amp;rsquo;t sure how to calculate the Big-O for this program because there didn&amp;rsquo;t seem to be any one unit of computation that made sense to use as the foundation of the algorithmic analysis. In the earlier examples it was the variable assignment, but in a web crawler there are so many different moving pieces that make up the whole program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, the implementation between web crawlers will determine different outcomes. So based on my implementation, the running time to handle a list of size &lt;code&gt;n&lt;/code&gt; containing nested sublists of size &lt;code&gt;x&lt;/code&gt; appears to be &lt;code&gt;O(nx)&lt;/code&gt;. I had not seen this type of Big-O analysis before, and is an indication of maybe I&amp;rsquo;m analysing the wrong things.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see my previous post for &lt;a href=&#34;/posts/algorithmic-complexity-in-python/&#34;&gt;common examples of Big-O&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So how did we come to &lt;code&gt;O(nx)&lt;/code&gt;? Here&amp;rsquo;s the breakdown:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I&amp;rsquo;m iterating over each list (there are &lt;code&gt;n&lt;/code&gt; of them), and each contains &lt;code&gt;x&lt;/code&gt; items, so you iterate over &lt;code&gt;nx&lt;/code&gt; items in all.&lt;/li&gt;&#xA;&lt;li&gt;The amount of work per item appears to be constant, i.e., &lt;code&gt;O(1)&lt;/code&gt; (it doesn&amp;rsquo;t appear to depend on &lt;code&gt;n&lt;/code&gt; or &lt;code&gt;x&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Multiplying those together, we see that the total time to handle that list is &lt;code&gt;O(nx)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The feedback I received was that Big-O might not be useful for analysing a &amp;lsquo;system&amp;rsquo; such as mine because Big-O analysis ignores the constant factors, where as for systems code, we often care about the constant factors a lot.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In other words: I was looking at the system from too high a view. I was looking at the whole rather than picking a specific sub implementation of a particular algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another issue is that not all operations are the same, and yet Big-O treats them as such. For example, a variable assignment is not as intensive (computationally or time based) as a network request that can suffer latency and require context switching etc. So in that case Big-O analysis isn&amp;rsquo;t useful for understanding the performance of the system in practice.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So &amp;ldquo;no&amp;rdquo;, it doesn&amp;rsquo;t make sense to use Big-O all the time. It&amp;rsquo;ll only make sense from a smaller &lt;em&gt;algorithmic&lt;/em&gt; perspective.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These are all useful things to keep in mind when thinking about Big-O time complexity analysis.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/calculating-big-o/</guid>
      <link>https://www.integralist.co.uk/posts/calculating-big-o/</link>
      <pubDate>Thu, 28 Feb 2019 00:00:00 +0000</pubDate>
      <title>Calculating Big-O</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In this post we&amp;rsquo;re going to review some different algorithmic time complexities. Let me begin by clarifying, when I say &amp;lsquo;algorithm&amp;rsquo; I mean: &amp;lsquo;logic written in code&amp;rsquo; and when I say &amp;lsquo;operation&amp;rsquo; I mean: &amp;lsquo;a unit of code was evaluated&amp;rsquo;, and that operation could be something as simple as &lt;code&gt;x + y&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;asymptotic-analysis&#34;&gt;Asymptotic Analysis&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Asymptotic analysis is the computing of an algorithm&amp;rsquo;s running time, and there are actually a few different variations that allow us to measure different aspects of that running time:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Big Omega&lt;/strong&gt;: represents the lower bound.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Big Theta&lt;/strong&gt;: represents both the lower and upper bounds.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Big O&lt;/strong&gt;: represents the upper bound.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re interested in the last notation in that list (&lt;a href=&#34;https://en.wikipedia.org/wiki/Big_O_notation&#34; target=&#34;_blank&#34;&gt;Big O notation&lt;/a&gt;) and what the various algorithmic complexity symbols mean when applied to simplified implementations of specific algorithms written in Python.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for selecting Big O over other notations is that it&amp;rsquo;s the most relevant for performance analysis, as it helps us to understand the worst case behaviour.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a fantastic &amp;lsquo;quick&amp;rsquo; reference for Big O notation is &lt;a href=&#34;http://bigocheatsheet.com/&#34; target=&#34;_blank&#34;&gt;bigocheatsheet.com&lt;/a&gt;, but also Python &lt;a href=&#34;https://wiki.python.org/moin/TimeComplexity&#34; target=&#34;_blank&#34;&gt;documents the time complexity&lt;/a&gt; associated with its various builtin functions (which is super useful).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;measuring-algorithmic-performance&#34;&gt;Measuring Algorithmic Performance&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When measuring the performance of an algorithm we&amp;rsquo;re interested in how the increase in input size will affect the growth rate of operations required, and this attribute is typically referred to as the algorithm&amp;rsquo;s &amp;lsquo;time complexity&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are two types of complexity we might be interested in (both dependant upon the length of the input to be processed):&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;time&lt;/strong&gt;: quantifies the amount of time taken by the algorithm.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;space&lt;/strong&gt;: quantifies the amount of memory used by the algorithm.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the Big O notation used to describe these complexities is telling us the &amp;lsquo;growth rate&amp;rsquo; of a function, which is typically referred to as the &amp;lsquo;&lt;strong&gt;order&lt;/strong&gt; of the function&amp;rsquo; (hence the &amp;lsquo;O&amp;rsquo; in Big O).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;orders-of-complexity&#34;&gt;Orders of Complexity&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Good:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(1)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(log n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(√n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;OK:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Bad:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n log n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Awful:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n^2)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(2^n)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n!)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when writing a logarithm you are expected to specify the base: &lt;code&gt;log 2(n)&lt;/code&gt; but with Big O notation you typically omit the two, resulting in: &lt;code&gt;O(log n)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;growth-types&#34;&gt;Growth Types&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(1)&lt;/code&gt;: &lt;a href=&#34;#constant-time&#34;&gt;constant time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(Log n)&lt;/code&gt;: &lt;a href=&#34;#logarithmic-time&#34;&gt;logarithmic time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(√n)&lt;/code&gt;: &lt;a href=&#34;#square-root-time&#34;&gt;square root time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n)&lt;/code&gt;: &lt;a href=&#34;#linear-time&#34;&gt;linear time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n Log n)&lt;/code&gt;: &lt;a href=&#34;#linearithmic-time&#34;&gt;linearithmic time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n*n)&lt;/code&gt;: &lt;a href=&#34;#quadratic-time&#34;&gt;quadratic time&lt;/a&gt; (squared)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n^2)&lt;/code&gt;: &lt;a href=&#34;#polynomial-time&#34;&gt;polynomial time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(2^n)&lt;/code&gt;: &lt;a href=&#34;#exponential-time&#34;&gt;exponential time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n!)&lt;/code&gt;: &lt;a href=&#34;#factorial-time&#34;&gt;factorial time&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;constant-time&#34;&gt;Constant Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm has &amp;lsquo;constant time&amp;rsquo; when the number of operations doesn&amp;rsquo;t change as the number of elements increase.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;l = []&#xA;l.append(1)&#xA;len(l)  # 1&#xA;&#xA;l = list(range(1000))&#xA;len(l)  # 1000&#xA;l.append(1)&#xA;len(l)  # 1001&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example code it doesn&amp;rsquo;t matter how many elements are contained with the list (&lt;code&gt;l&lt;/code&gt;). Regardless of whether we append a new element to a list consisting of one element or a thousand elements, the time complexity is &lt;code&gt;O(1)&lt;/code&gt; constant time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similarly for acquiring the length of a list &lt;code&gt;len(l)&lt;/code&gt;, regardless of whether the list has one element or a thousand, the time complexity stays constant time.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;logarithmic-time&#34;&gt;Logarithmic Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;logarithmic&amp;rsquo; when the number of operations &lt;em&gt;decreases&lt;/em&gt; by a specific factor with each step.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm for searching a specific element from a given input:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def binary_search(l, item):&#xA;    first = 0&#xA;    last = len(l)-1&#xA;    found = False&#xA;&#xA;    while first&amp;lt;=last and not found:&#xA;        midpoint = round((first + last)/2)&#xA;        if l[midpoint] == item:&#xA;            found = True&#xA;        else:&#xA;            if item &amp;lt; l[midpoint]:&#xA;                last = midpoint-1&#xA;            else:&#xA;                first = midpoint+1&#xA;&#xA;    return found&#xA;&#xA;input = [0, 1, 2, 8, 13, 17, 19, 32, 42,]&#xA;&#xA;print(binary_search(input, 3))   # found: False&#xA;print(binary_search(input, 13))  # fount: True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The algorithm used here is known as a &amp;lsquo;binary search&amp;rsquo; and only works when the given input is sorted/ordered. It works on the principle of dividing the range of elements to be searched by two.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This algorithm fits the requirements of logarithmic time complexity because instead of iterating over the entire input list, we actually &lt;em&gt;shorten&lt;/em&gt; the input by half on each &amp;lsquo;step&amp;rsquo; of the algorithm.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I discuss &lt;a href=&#34;/posts/big-o-for-beginners/#binary-search&#34;&gt;binary search&lt;/a&gt; in more detail in an older post.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;square-root-time&#34;&gt;Square Root Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm has &amp;lsquo;sqrt&amp;rsquo; (or &lt;code&gt;√&lt;/code&gt;) time complexity when the number of operations increases dependant on the number of primes under the square root of the given number.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm for checking if a number is a prime. This would have square root time complexity:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def is_prime_number(x):&#xA;    if x &amp;gt;= 2:&#xA;        for y in range(2,x):&#xA;            # if x divides with zero remainder (i.e. equal to bool False)&#xA;            if not (x % y):&#xA;                return False&#xA;    else:&#xA;        return False&#xA;    return True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;linear-time&#34;&gt;Linear Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;linear&amp;rsquo; when the number of operations increases linearly with the number of elements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm for searching a specific element from a given input:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def search(x, input):&#xA;    for i in input:&#xA;        print(i)&#xA;        if i == x:&#xA;            print(&#39;found element&#39;)&#xA;            return&#xA;&#xA;search(5, range(10))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This example &lt;code&gt;search&lt;/code&gt; function will loop over every element until it finds the number &lt;code&gt;5&lt;/code&gt;, resulting in it having &lt;code&gt;O(n)&lt;/code&gt; linear time complexity. Meaning: if the input range changes from &lt;code&gt;10&lt;/code&gt; to &lt;code&gt;1000&lt;/code&gt;, then the number of operations (i.e. loop iterations) increases linearly with it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The worst case scenario is if &lt;code&gt;x&lt;/code&gt; happens to be a number that doesn&amp;rsquo;t exist in the given input. We would have to iterate over the entire input before we realized the number didn&amp;rsquo;t exist.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a much better algorithm to use (if the input was guaranteed to be ordered/sorted) would be a &lt;a href=&#34;/posts/big-o-for-beginners/#binary-search&#34;&gt;binary search&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s interesting to keep in mind is that there are algorithms that are slower still than the example we&amp;rsquo;ve given above but are &lt;em&gt;still&lt;/em&gt; considered to be &amp;lsquo;linear time&amp;rsquo; (e.g. &lt;code&gt;O(n)&lt;/code&gt;). Consider a collection of ten items that you loop over twice! That&amp;rsquo;s twice as many operations as our initial example but it&amp;rsquo;s still &lt;code&gt;O(n)&lt;/code&gt; and not something like &lt;code&gt;O(n*2)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why is that? Well, it stems from how you &lt;em&gt;calculate&lt;/em&gt; algorithmic complexity (see &lt;a href=&#34;/posts/calculating-big-o/&#34;&gt;my blog post on the subject&lt;/a&gt;). But in essence the calculation starts off very explicit until you identify which portion of the algorithm is the &amp;lsquo;dominant&amp;rsquo; (e.g. as the size of the input grows, which part of the algorithm gets worse). In the case of &lt;code&gt;O(n*2)&lt;/code&gt; the &amp;lsquo;constant&amp;rsquo; value is &lt;code&gt;2&lt;/code&gt;, but if the collection size changed from &lt;code&gt;10&lt;/code&gt; to &lt;code&gt;1000&lt;/code&gt; then (that being the &lt;code&gt;n&lt;/code&gt; part) the &lt;code&gt;n&lt;/code&gt; becomes the &amp;lsquo;dominant&amp;rsquo; portion of the algorithm and so we can simplify big-o to just &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;linearithmic-time&#34;&gt;Linearithmic Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;linearithmic&amp;rsquo; when the number of operations increases by the number of elements (i.e. linear time) times the result of &lt;code&gt;log n&lt;/code&gt; (i.e. logarithmic time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the &amp;lsquo;quick sort&amp;rsquo; algorithm whose implementation (below) selects a random element as the &amp;lsquo;pivot&amp;rsquo; and then loops the entire input list (minus the pivot) in order to identify elements that are less than the pivot and elements that are greater than the pivot (this is the &amp;lsquo;reduce by half&amp;rsquo; logarithmic principle). The function recursively calls itself passing in smaller and smaller subsets of input which are iterated over:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from random import randrange&#xA;&#xA;input = [10, 5, 2, 3, 7, 0, 9, 12]&#xA;&#xA;def quicksort(arr):&#xA;    if len(arr) &amp;lt; 2:&#xA;        return arr&#xA;    else:&#xA;        rand = randrange(0, len(arr))  # grab a random index&#xA;        pivot = arr.pop(rand)&#xA;        less = [i for i in arr if i &amp;lt;= pivot]&#xA;        greater = [i for i in arr if i &amp;gt; pivot]&#xA;        return quicksort(less) + [pivot] + quicksort(greater)&#xA;&#xA;print(&amp;quot;sorted:  &amp;quot;, quicksort(input))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I discuss &lt;a href=&#34;/posts/big-o-for-beginners/#quick-sort&#34;&gt;quick sort&lt;/a&gt; in more detail in an older post.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;quadratic-time&#34;&gt;Quadratic Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;quadratic&amp;rsquo; when the number of operations become the square of the number of elements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm whose implementation is looping over some input and then nesting another loop of that same input:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def search(input):&#xA;    for i in input:&#xA;        for j in input:&#xA;            print(f&#39;i: {i}, j: {j}&#39;)&#xA;&#xA;search(range(10))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This example &lt;code&gt;search&lt;/code&gt; function will loop over every element in &lt;code&gt;input&lt;/code&gt; and then for each item iterated over it&amp;rsquo;ll loop through the same top-level input collection again, resulting in it having &lt;code&gt;O(n*n)&lt;/code&gt; quadratic time complexity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In our example code our collection is a list of ten items. Item 1 is the initial list value &lt;code&gt;0&lt;/code&gt;, and for that we&amp;rsquo;ll loop again ten times. We move to Item 2 (which is the value &lt;code&gt;1&lt;/code&gt;) and &lt;em&gt;again&lt;/em&gt; we&amp;rsquo;ll end up looping ten times &amp;hellip;and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means if the input range changed from &lt;code&gt;10&lt;/code&gt; to &lt;code&gt;1000&lt;/code&gt;, then the number of operations (i.e. total loop iterations) increases as a square of the number of elements.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;polynomial-time&#34;&gt;Polynomial Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A polynomial time complexity &lt;em&gt;is&lt;/em&gt; effectively a &amp;lsquo;quadratic&amp;rsquo; algorithm in the sense that with quadratic &lt;code&gt;O(n*n)&lt;/code&gt; (where &lt;code&gt;n&lt;/code&gt; is &lt;code&gt;10&lt;/code&gt;) we have a number of operations equal to &lt;code&gt;100&lt;/code&gt;, and if we compare that to polynomial &lt;code&gt;O(n^2)&lt;/code&gt; (where &lt;code&gt;n&lt;/code&gt; is &lt;code&gt;10&lt;/code&gt;) then again we have the number of operations equal to &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the difference comes when the exponent (&lt;code&gt;2&lt;/code&gt;) in the polynomial equation is increased (where as with quadratic it will always be a squared number). For example, &lt;code&gt;O(n^3)&lt;/code&gt; is also referred to as being polynominal.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;exponential-time&#34;&gt;Exponential Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;exponential&amp;rsquo; when the number of operations grows exponentially with the number of elements (i.e. growth whose rate becomes ever more rapid in proportion to the growing total number or size).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;exponential time complexity &lt;code&gt;O(2^n)&lt;/code&gt; is worse than polynomial &lt;code&gt;O(n^2)&lt;/code&gt; because maths tells us that &lt;em&gt;over time&lt;/em&gt; exponential will quickly overtake polynomial.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm whose implementation is calculating fibonacci numbers (which grows exponentially relative to the calculated output).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The fibonacci numbers are calculated as the addition of the last element with the current element. The sequence itself starts at zero, so the first seven numbers in the sequence would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0, 1, 1, 2, 3, 5, 8&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see &lt;code&gt;0 + 1 = 1&lt;/code&gt;, then &lt;code&gt;1 + 1 = 2&lt;/code&gt;, then &lt;code&gt;1 + 2 = 3&lt;/code&gt; and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a possible implementation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def fibonacci(num):&#xA;    if (num &amp;lt;= 1):&#xA;       return num&#xA;    return fibonacci(num - 2) + fibonacci(num - 1)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Meaning, if we wanted the sixth number in the sequence (&lt;code&gt;8&lt;/code&gt;) we would call our function with &lt;code&gt;fibonacci(6)&lt;/code&gt; (as the numbers are zero indexed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Recursive functions can be difficult to build a mental model from, so let&amp;rsquo;s attempt to pick it apart with some pseudo-logic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# f is our fibonacci function&#xA;# the logic below is the result of calling f(3)&#xA;# the third sequence number is 2&#xA;# remembering the sequence is zero indexed&#xA;# [0] = 0, [1] = 1, [2] = 1, [3] = 2, [4] = 3, [5] = 5, [6] = 8&#xA;&#xA;f(3):&#xA;  3 - 2 = 1&#xA;  3 - 1 = 2&#xA;  f(1) + f(2)&#xA;&#xA;  f(1) = 1&#xA;  f(2) =&#xA;     2 - 2 = 0&#xA;     2 - 1 = 1&#xA;     f(0) = 0&#xA;     f(1) = 1&#xA;&#xA;  1 + 1 = 2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;factorial-time&#34;&gt;Factorial Time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An algorithm is &amp;lsquo;factorial&amp;rsquo; when the number of operations increases in line with the number of permutations associated with the number of elements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider an algorithm whose implementation is calculating the factorial, i.e. the number of permutations, for a given number (this is classically known as &amp;lsquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Travelling_salesman_problem&#34; target=&#34;_blank&#34;&gt;the travelling salesman&lt;/a&gt;&amp;rsquo; problem):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def factorial(n):&#xA;    for i in range(n):&#xA;        print(f&#39;iteration [{i}]: {n}&#39;)&#xA;        factorial(n-1)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The factorial function recursively calls itself, and the output of this function should be the various permutations of the given number:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;3&#xA;2&#xA;1&#xA;2&#xA;1&#xA;3&#xA;2&#xA;1&#xA;2&#xA;1&#xA;3&#xA;2&#xA;1&#xA;2&#xA;1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are six permutations for a number up to three (&lt;code&gt;123, 132, 213, 231, 312, 321&lt;/code&gt;), but imagine if you wanted the various permutations of a number up to ten?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The calculation for that would yield a disastrously large number:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10*9*8*7*6*5*4*3*2*1 = 3,628,800&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Hence this is the worst performing time complexity of the lot.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I discuss &lt;a href=&#34;/posts/big-o-for-beginners/#factorials&#34;&gt;factorials&lt;/a&gt; in more detail in an older post.&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/algorithmic-complexity-in-python/</guid>
      <link>https://www.integralist.co.uk/posts/algorithmic-complexity-in-python/</link>
      <pubDate>Sat, 02 Feb 2019 00:00:00 +0000</pubDate>
      <title>Algorithmic Complexity in Python</title>
    </item>
    <item>
      <description>&lt;p&gt;In this post we will be looking briefly at, and at a high-level, the various data types and data structures used in designing software systems, and from which specific types of algorithms can subsequently be built upon and optimized for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are &lt;em&gt;many&lt;/em&gt; data structures, and even the ones that are covered here have many nuances that make it impossible to cover every possible detail. But my hope is that this will give you an interest to research them further.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;data-types&#34;&gt;Data Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A data type is an &lt;a href=&#34;https://english.stackexchange.com/a/28098/334144&#34; target=&#34;_blank&#34;&gt;attribute&lt;/a&gt; of data which tells the compiler (or interpreter) how the programmer intends to use the data.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Scalar&lt;/strong&gt;: basic building block (boolean, integer, float, char etc.)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Composite&lt;/strong&gt;: any data type (struct, array, string etc.) composed of scalars or composite types (also referred to as a &amp;lsquo;compound&amp;rsquo; type).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Abstract&lt;/strong&gt;: data type that is defined by its behaviour (tuple, set, stack, queue, graph etc).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You might also have heard of a &amp;lsquo;primitive&amp;rsquo; type, which is sometimes confused with the &amp;lsquo;scalar&amp;rsquo; type. A primitive is typically used to represent a &amp;lsquo;value type&amp;rsquo; (e.g. pass-by-value semantics) and this contrasts with &amp;lsquo;reference types&amp;rsquo; (e.g. pass-by-reference semantics).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If we consider a composite type, such as a &amp;lsquo;string&amp;rsquo;, it &lt;em&gt;describes&lt;/em&gt; a data structure which contains a sequence of char scalars (characters), and as such is referred to as being a &amp;lsquo;composite&amp;rsquo; type. Whereas the underlying &lt;em&gt;implementation&lt;/em&gt; of the string composite type is typically implemented using an array data structure (we&amp;rsquo;ll cover &lt;a href=&#34;#data-structures&#34;&gt;data structures&lt;/a&gt; shortly).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in a language like C the length of the string&amp;rsquo;s underlying array will be the number of characters in the string followed by a &amp;lsquo;&lt;a href=&#34;/posts/concepts-from-the-c-programming-language/#null-terminator&#34;&gt;null terminator&lt;/a&gt;&amp;rsquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;An abstract data type (ADT) describes the expected &lt;em&gt;behaviour&lt;/em&gt; associated with a concrete data structure. For example, a &amp;lsquo;list&amp;rsquo; is an abstract data type which represents a countable number of ordered values, but again the &lt;em&gt;implementation&lt;/em&gt; of such a data type could be implemented using a variety of different data structures, one being a &amp;lsquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linked_list&#34; target=&#34;_blank&#34;&gt;linked list&lt;/a&gt;&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;an ADT describes behaviour from the perspective of a consumer of that type (e.g. it describes certain operations that can be performed on the data itself). For example, a list data type can be considered a sequence of values and so one available operation/behaviour would be that it must be iterable.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;data-structures&#34;&gt;Data Structures&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A data structure is a collection of data type &amp;lsquo;values&amp;rsquo; which are stored and organized in such a way that it allows for efficient access and modification. In some cases a data structure can become the underlying implementation for a particular data type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, composite data types are data structures that are composed of scalar data types and/or other composite types, whereas an abstract data type will define a set of behaviours (almost like an &amp;lsquo;interface&amp;rsquo; in a sense) for which a particular data structure can be used as the concrete implementation for that data type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we think of data structures, there are generally four forms:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Linear&lt;/strong&gt;: arrays, lists&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Tree&lt;/strong&gt;: binary, heaps, space partitioning etc.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Hash&lt;/strong&gt;: distributed hash table, hash tree etc.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Graphs&lt;/strong&gt;: decision, directed, acyclic etc.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for a more complete reference,&lt;br&gt;&#xA;please see this &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_data_structures&#34; target=&#34;_blank&#34;&gt;Wikipedia article&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now take a look at the properties that make up a few of the more well known data structures.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;array&#34;&gt;Array&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An array is a finite group of data, which is allocated contiguous (i.e. sharing a common border) memory locations, and each element within the array is accessed via an index key (typically numerical, and zero based).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The name assigned to an array is typically a pointer to the first item in the array. Meaning that given an array identifier of &lt;code&gt;arr&lt;/code&gt; which was assigned the value &lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&lt;/code&gt;, in order to access the &lt;code&gt;&amp;quot;b&amp;quot;&lt;/code&gt; element you would use the index 1 to lookup the value: &lt;code&gt;arr[1]&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Arrays are traditionally &amp;lsquo;finite&amp;rsquo; in size, meaning you define their length/size (i.e. memory capacity) up front, but there is a concept known as &amp;lsquo;dynamic arrays&amp;rsquo; (and of which you&amp;rsquo;re likely more familiar with when dealing with certain high-level programmings languages) which supports the &lt;em&gt;growing&lt;/em&gt; (or resizing) of an array to allow for more elements to be added to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to resize an array you first need to allocate a new slot of memory (in order to copy the original array element values over to), and because this type of operation is quite &amp;lsquo;expensive&amp;rsquo; (in terms of computation and performance) you need to be sure you increase the memory capacity just the right amount (typically double the original size) to allow for more elements to be added at a later time without causing the CPU to have to resize the array over and over again unnecessarily.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One consideration that needs to be given is that you don&amp;rsquo;t want the resized memory space to be &lt;em&gt;too&lt;/em&gt; large, otherwise finding an appropriate slot of memory becomes more tricky.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When dealing with modifying arrays you also need to be careful because this requires significant overhead due to the way arrays are allocated memory slots.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you imagine you have an array and you want to remove an element from the middle of the array, try to think about that in terms of memory allocation: an array needs its indexes to be contiguous, and so we have to re-allocate a new chunk of memory and copy over the elements that were placed &lt;em&gt;around&lt;/em&gt; the deleted element.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These types of operations, when done at scale, are the foundation behind why it&amp;rsquo;s important to have an understanding of how data structures are implemented. The reason being, when you&amp;rsquo;re writing an algorithm you will hopefully be able to recognize when you&amp;rsquo;re about to do something (let&amp;rsquo;s say modify an array many times within a loop construct) that could ultimately end up being quite a memory intensive set of operations.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;interestingly I&amp;rsquo;ve discovered that in some languages an array (as in the composite data type) has been implemented using a variety of different data structures such as hash table, linked list, and even a search tree.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;linked-list&#34;&gt;Linked List&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A linked list is different to an array in that the order of the elements within the list are not determined by a contiguous memory allocation. Instead the elements of the linked list can be sporadically placed in memory due to its design, which is that each element of the list (also referred to as a &amp;lsquo;node&amp;rsquo;) consists of two parts:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;the data&lt;/li&gt;&#xA;&lt;li&gt;a pointer&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The data is what you&amp;rsquo;ve assigned to that element/node, whereas the pointer is a memory address reference to the next node in the list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/linked-list.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/linked-list.png&#34; alt=&#34;linked list&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also unlike an array, there is no index access. So in order to locate a specific piece of data you&amp;rsquo;ll need to traverse the entire list until you find the data you&amp;rsquo;re looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is one of the key performance characteristics of a linked list, and is why (for most implementations of this data structure) you&amp;rsquo;re not able to &lt;em&gt;append&lt;/em&gt; data to the list (because if you think about the performance of such an operation it would require you to traverse the entire list to find the end/last node). Instead linked lists generally will only allow &lt;em&gt;prepending&lt;/em&gt; to a list as it&amp;rsquo;s much quicker. The newly added node will then have its pointer set to the original &amp;lsquo;head&amp;rsquo; of the list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is also a modified version of this data structure referred to as a &amp;lsquo;doubly linked list&amp;rsquo; which is essentially the same concept but with the exception of a third attribute for each node: a pointer to the &lt;em&gt;previous&lt;/em&gt; node (whereas a normal linked list would only have a pointer to the &lt;em&gt;following&lt;/em&gt; node).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;again, performance considerations need to be given for the types of operations being made with a doubly linked list, such as the addition or removal of nodes in the list, because you now have not only the pointers to the following node that need to be updated, but also the pointers back to a previous node that now also need to be updated.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;tree&#34;&gt;Tree&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The concept of a &amp;lsquo;tree&amp;rsquo; in its simplest terms is to represent a hierarchical tree structure, with a root value and subtrees of children (with a parent node), represented as a set of linked nodes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/tree.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/tree.png&#34; alt=&#34;tree&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A tree contains &amp;ldquo;nodes&amp;rdquo; (a node has a value associated with it) and each node is connected by a line called an &amp;ldquo;edge&amp;rdquo;. These lines represent the &lt;em&gt;relationship&lt;/em&gt; between the nodes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The top level node is known as the &amp;ldquo;root&amp;rdquo; and a node with no children is a &amp;ldquo;leaf&amp;rdquo;. If a node is connected to other nodes, then the preceeding node is referred to as the &amp;ldquo;parent&amp;rdquo;, and nodes following it are &amp;ldquo;child&amp;rdquo; nodes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are various incarnations of the basic tree structure, each with their own unique characteristics and performance considerations:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Binary Tree&lt;/li&gt;&#xA;&lt;li&gt;Binary Search Tree&lt;/li&gt;&#xA;&lt;li&gt;Red-Black Tree&lt;/li&gt;&#xA;&lt;li&gt;B-tree&lt;/li&gt;&#xA;&lt;li&gt;Weight-balanced Tree&lt;/li&gt;&#xA;&lt;li&gt;Heap&lt;/li&gt;&#xA;&lt;li&gt;Abstract Syntax Tree&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;binary-tree&#34;&gt;Binary Tree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A binary tree is a &amp;lsquo;rooted tree&amp;rsquo; and consists of nodes which have, at most, two children. This is as the name suggests (i.e. &amp;lsquo;binary&amp;rsquo;: 0 or 1), so &lt;em&gt;two&lt;/em&gt; potential values/directions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Rooted trees suggest a notion of &lt;em&gt;distance&lt;/em&gt; (i.e. distance from the &amp;lsquo;root&amp;rsquo; node)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in some cases you might refer to a binary tree as an &amp;lsquo;undirected&amp;rsquo; graph (we&amp;rsquo;ll look at &lt;a href=&#34;#graph&#34;&gt;graphs&lt;/a&gt; shortly) if talking in the context of graph theory or mathematics.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Binary trees are the building blocks of &lt;em&gt;other&lt;/em&gt; tree data structures (see also: &lt;a href=&#34;https://stackoverflow.com/a/2200588/4288305&#34; target=&#34;_blank&#34;&gt;this reference&lt;/a&gt; for more details), and so when it comes to the performance of certain operations (insertion, deletion etc) consideration needs to be given to the number of &amp;lsquo;hops&amp;rsquo; that need to be made as well as the re-balancing of the tree (much the same way as the pointers for a linked list need to be updated).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;binary-search-tree&#34;&gt;Binary Search Tree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A binary search tree is a &amp;lsquo;sorted&amp;rsquo; tree, and is named as such because it helps to support the use of a &amp;lsquo;binary search&amp;rsquo; algorithm for searching more efficiently for a particular node (more on that later).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/binary-search-tree.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/binary-search-tree.png&#34; alt=&#34;binary search tree&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To understand the idea of the nodes being &amp;lsquo;sorted&amp;rsquo; (or &amp;lsquo;ordered&amp;rsquo;) we need to compare the left node with the right node. The left node should always be a lesser number than the right node, and the parent node should be the decider as to whether a child node is placed to the left or the right.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the example image above, where we can see the root node is &lt;code&gt;8&lt;/code&gt;. Let&amp;rsquo;s imagine we&amp;rsquo;re going to construct this tree.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We start with &lt;code&gt;8&lt;/code&gt; as the root node and then we&amp;rsquo;re given the number &lt;code&gt;3&lt;/code&gt; to insert into the tree. At this point the underlying logic for constructing the tree will know that the number &lt;code&gt;3&lt;/code&gt; is &lt;em&gt;less&lt;/em&gt; than &lt;code&gt;8&lt;/code&gt; and so it&amp;rsquo;ll first check to see if there is already a left node (there isn&amp;rsquo;t), so in this scenario the logic will determine that the tree should have a new left node under &lt;code&gt;8&lt;/code&gt; and assign it the value of &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if we give the number &lt;code&gt;6&lt;/code&gt; to be inserted, the logic will find that again it is less than &lt;code&gt;8&lt;/code&gt; and so it&amp;rsquo;ll check for a left node. There is a left node (it has a value of &lt;code&gt;3&lt;/code&gt;) and so the value &lt;code&gt;6&lt;/code&gt; is &lt;em&gt;greater&lt;/em&gt; than &lt;code&gt;3&lt;/code&gt;. This means the logic will now check to see if there is a right node (there isn&amp;rsquo;t) and subsequently creates a new right node and assigns it the value &lt;code&gt;6&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This process continues on and on until the tree has been provided all of the relevant numbers to be sorted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence what this sorted tree design facilitates is the means for an operation (such as lookup, insertion, deletion) to only take, on average, time proportional to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Logarithm&#34; target=&#34;_blank&#34;&gt;logarithm&lt;/a&gt; of the number of items stored in the tree.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if there were 1000 nodes in the tree, and we wanted to find a specific node, then the average case number of comparisons (i.e. comparing left/right nodes) would be &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By using the logarithm to calculate this we get: &lt;code&gt;log 2(10) = 1024&lt;/code&gt; which is the inverse of the exponentiation &lt;code&gt;2^10&lt;/code&gt; (&amp;ldquo;2 raised to the power of 10&amp;rdquo;), so this says we&amp;rsquo;ll execute 10 comparisons before finding the node we were after.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To break that down a bit further: the exponentiation calculation is &lt;code&gt;1024 = 2 × 2 × 2 x 2 x 2 x 2 × 2 × 2 x 2 x 2 = 2^10&lt;/code&gt;, so the &amp;ldquo;logarithm to base 2&amp;rdquo; of 10 is 1024.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The logarithm (i.e. the inverse function of exponentiation) of 1000 to base 2, in this case abstracted to &lt;code&gt;n&lt;/code&gt;, is denoted as &lt;code&gt;log 2 (n)&lt;/code&gt;, but typically the base 2 is omitted to just &lt;code&gt;log(n)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When determining the &amp;lsquo;time complexity&amp;rsquo; for operations on this type of data structure we typically use &amp;lsquo;Big O&amp;rsquo; notation and thus the Big O complexity would be defined as &lt;code&gt;O(log n)&lt;/code&gt; for the average search case (which is good), but the &lt;em&gt;worst case&lt;/em&gt; for searching would still be &lt;code&gt;O(n)&lt;/code&gt; linear time (which is bad &amp;ndash; and I&amp;rsquo;ll explain why in the next section on &lt;a href=&#34;#red-black-tree&#34;&gt;red-black trees&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve covered the basics of logarithm and binary search in a &lt;a href=&#34;/posts/big-o-for-beginners/#logarithms&#34;&gt;much older post&lt;/a&gt; about Big O notation, and so I&amp;rsquo;ll refer you to that for more details.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Similarly when considering complexity for a particular algorithm, we should take into account both &amp;lsquo;time&amp;rsquo; and &amp;lsquo;space&amp;rsquo; complexity. The latter is the amount of memory necessary for the algorithm to execute and is similar to time complexity in that we&amp;rsquo;re interested in how that resource (time vs space) will change and affect the performance depending on the size of the input.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;red-black-tree&#34;&gt;Red-Black Tree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The performance of a binary search tree is dependant on the height of the tree. Meaning we should aim to keep the tree as &amp;lsquo;balanced&amp;rsquo; as possible, otherwise the logarithm performance is lost in favor of linear time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To understand why that is, consider the following data stored in an array:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[1, 2, 3, 4]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we construct a binary search tree from this data, what we would ultimately end up with is a very &amp;lsquo;unbalanced&amp;rsquo; tree in the sense that all the nodes would be to the right, and none to the left.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/bst-unbalanced.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/bst-unbalanced.png&#34; alt=&#34;bst unbalanced&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we search this type of tree (which for all purposes is effectively a linked list) we would, worst case, end up with linear time complexity: &lt;code&gt;O(n)&lt;/code&gt;. To resolve that problem we need a way to balance the nodes in the tree.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where the concept of a red-black tree comes in to help us. With a red-black tree (due to it being consistently balanced) we get &lt;code&gt;O(log n)&lt;/code&gt; for search/insert/delete operations (which is great).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s consider the properties of a red-black tree:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Each node is either red or black.&lt;/li&gt;&#xA;&lt;li&gt;The root node is always black.&lt;/li&gt;&#xA;&lt;li&gt;All leaves are &amp;lsquo;NIL&amp;rsquo; and should also be black.&lt;/li&gt;&#xA;&lt;li&gt;All red nodes should have two black child nodes.&lt;/li&gt;&#xA;&lt;li&gt;All paths from given node to NIL must have same num of black nodes.&lt;/li&gt;&#xA;&lt;li&gt;New nodes should be red by default (we&amp;rsquo;ll clarify below).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when counting nodes we don&amp;rsquo;t include the root node, and we count each black node up to (and including) the NIL node.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/red-black-tree.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/red-black-tree.png&#34; alt=&#34;red black tree&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The height of the tree is referred to as its &amp;lsquo;black-height&amp;rsquo;, which is the number of black nodes (not including the root) to the furthest leaf, and should be no longer than twice as long as the length of the shortest path (the nearest NIL).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These properties are what enable the red-black tree to provide the performance characteristics it has (i.e. &lt;code&gt;O(log n)&lt;/code&gt;), and so whenever changes are made to the tree we want to aim to keep the tree height as short as possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On every node insertion, or deletion, we need to ensure we have not violated the red-black properties. If we do, then there are two possible steps that we have to consider in order to keep the tree appropriately balanced (which we&amp;rsquo;ll check in this order):&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Recolour the node&lt;/strong&gt;&lt;br&gt;&#xA;in the case of a red node no longer having two black child nodes.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Make a &lt;a href=&#34;https://en.wikipedia.org/wiki/Tree_rotation&#34; target=&#34;_blank&#34;&gt;rotation&lt;/a&gt; (left/right)&lt;/strong&gt;&lt;br&gt;&#xA;in the case where recolouring then requires a structural change.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The goal of a rotation is to decrease the height of the tree. The way we do this is by moving larger subtrees up the tree, and smaller subtrees down the tree. We rotate in the direction of the smaller subtree, so if the smaller side is the right side we&amp;rsquo;ll do a right rotation.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is an inconsistency between what node/subtree is affected by a rotation. Does the subtree being moved into the parent position indicate the direction or does the target node affected by the newly moved subtree indicate the direction (I&amp;rsquo;ve opted for the latter, as we&amp;rsquo;ll see below, but be aware of this when reading research material).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In essence there are three steps that need to be applied to the target node (&lt;code&gt;T&lt;/code&gt;) being rotated, and this is the same for either a left rotation or a right rotation. Let&amp;rsquo;s quickly look at both of these rotation movements:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Left Rotation&lt;/strong&gt;:&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;T&lt;/code&gt;&amp;rsquo;s right node (&lt;code&gt;R&lt;/code&gt;) is unset &amp;amp; becomes &lt;code&gt;T&lt;/code&gt;&amp;rsquo;s parent †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;R&lt;/code&gt;&amp;rsquo;s &lt;em&gt;original&lt;/em&gt; left node &lt;code&gt;L&lt;/code&gt; is now orphaned.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;T&lt;/code&gt;&amp;rsquo;s right node is now set to &lt;code&gt;L&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† we now find &lt;code&gt;R&lt;/code&gt;&amp;rsquo;s left pointer has to be set to &lt;code&gt;T&lt;/code&gt; (in order for it to become the parent node), meaning &lt;code&gt;R&lt;/code&gt;&amp;rsquo;s original left pointer is orphaned.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Right Rotation&lt;/strong&gt;:&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;T&lt;/code&gt;&amp;rsquo;s left node (&lt;code&gt;L&lt;/code&gt;) is unset &amp;amp; becomes &lt;code&gt;T&lt;/code&gt;&amp;rsquo;s parent †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;L&lt;/code&gt;&amp;rsquo;s &lt;em&gt;original&lt;/em&gt; right node &lt;code&gt;R&lt;/code&gt; is now orphaned.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;T&lt;/code&gt;&amp;rsquo;s left node is now set to &lt;code&gt;R&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† we now find &lt;code&gt;L&lt;/code&gt;&amp;rsquo;s right pointer has to be set to &lt;code&gt;T&lt;/code&gt; (in order for it to become the parent node), meaning &lt;code&gt;L&lt;/code&gt;&amp;rsquo;s original right pointer is orphaned.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now visualize the movements for both rotations:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Left Rotation&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/red-black-tree-left-rotation.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/red-black-tree-left-rotation.png&#34; alt=&#34;red black tree left rotation&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Right Rotation&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/red-black-tree-right-rotation.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/red-black-tree-right-rotation.png&#34; alt=&#34;red black tree right rotation&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;rotations are confusing, so I recommend watching &lt;a href=&#34;https://www.youtube.com/watch?v=95s3ndZRGbk&#34; target=&#34;_blank&#34;&gt;this short video&lt;/a&gt; for some examples and pseudo-code.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;b-tree&#34;&gt;B-tree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A B-tree is a sorted tree that is very similar in essence to a red-black tree in that it is self-balancing and as such can guarantee logarithmic time for search/insert/delete operations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A B-tree is useful for large read/writes of data and is commonly used in the design of databases and file systems, but it&amp;rsquo;s important to note that a B-tree is &lt;em&gt;not&lt;/em&gt; a binary search tree because it allows more than two child nodes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reasoning for allowing multiple children for a node is to ensure the height of the tree is kept as small as possible. The rationale is that B-trees are designed for handling huge amounts of data which itself cannot exist in-memory, and so that data is pulled (in chunks) from external sources.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This type of I/O is expensive and so keeping the tree &amp;lsquo;fat&amp;rsquo; (i.e. to have a very short height instead of lots of node subtrees creating extra length) helps to reduce the amount of disk access.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The design of a B-tree means that all nodes allow a set range for its children but not all nodes will need the full range, meaning that there is a potential for wasted space.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are also variants of the B-tree, such as B+ trees and B* trees (which we&amp;rsquo;ll leave as a research exercise for the reader).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;weight-balanced-tree&#34;&gt;Weight-balanced Tree&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A weight-balanced tree is a form of binary search tree and is similar in spirit to a weighted graph, in that individual nodes are &amp;lsquo;weighted&amp;rsquo; to indicate the more likely successful route with regards to searching for a particular value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The search performance is the driving motivation for using this data structure, and typically used for implementing sets and dynamic dictionaries.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;binary-heap&#34;&gt;Binary Heap&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A binary heap tree is a binary tree, not a binary search tree, and so it&amp;rsquo;s not a sorted tree. It has some additional properties that we&amp;rsquo;ll look at in a moment, but in essence the purpose of this data structure is primarily to be used as the underlying implementation for a &lt;a href=&#34;https://en.wikipedia.org/wiki/Priority_queue&#34; target=&#34;_blank&#34;&gt;priority queue&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The additional properties associated with a binary heap are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;heap property&lt;/strong&gt;: the node value is either greater (or lesser depending on the direction of the heap) or equal to the value of its parent.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;shape property&lt;/strong&gt;: if the last level of the tree is incomplete, the missing nodes are filled.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The insertion and deletion operations yield a time complexity of &lt;code&gt;O(log n)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some examples of a max and min binary heap tree structure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Max Heap&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/binary-heap-max.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/binary-heap-max.png&#34; alt=&#34;binary heap max&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Min Heap&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/binary-heap-min.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/binary-heap-min.png&#34; alt=&#34;binary heap min&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;hash-table&#34;&gt;Hash Table&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A hash table is a data structure which is capable of maping &amp;lsquo;keys&amp;rsquo; to &amp;lsquo;values&amp;rsquo;, and you&amp;rsquo;ll typically find this is abstracted and enhanced with additional behaviours by many high-level programming languages such that they behave like an &amp;lsquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Associative_array&#34; target=&#34;_blank&#34;&gt;associative array&lt;/a&gt;&amp;rsquo; abstract data type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Python it&amp;rsquo;s called a &amp;lsquo;dictionary&amp;rsquo; and has the following structure (on top of which are functions such as &lt;code&gt;del&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; etc that can manipulate the underlying data):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;table = {&#39;name&#39;: &#39;foobar&#39;,&#xA;         &#39;number&#39;: 123}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The keys for the hash table are determined by way of a &lt;a href=&#34;https://en.wikipedia.org/wiki/Hash_function&#34; target=&#34;_blank&#34;&gt;hash function&lt;/a&gt; but implementors need to be mindful of hash &amp;lsquo;collisions&amp;rsquo; which can occur if the hash function isn&amp;rsquo;t able to create a distinct or unique key for the table.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The better the hash generation, the more &lt;em&gt;distributed&lt;/em&gt; the keys will be, and thus less likely to collide. Also the size of the underlying array data structure needs to accommodate the type of hash function used for the key generation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if using modular arithmetic you might find the array needs to be sized to a prime number.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many techniques for resolving hashing collisions, but here are two that I&amp;rsquo;ve encountered:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Separate Chaining&lt;/li&gt;&#xA;&lt;li&gt;Linear Probing&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;separate-chaining&#34;&gt;Separate Chaining&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;With this option our keys will contain a nested data structure, and we&amp;rsquo;ll use a technique for storing our conflicting values into this nested structure, allowing us to store the same hashed value key in the top level of the array.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;linear-probing&#34;&gt;Linear Probing&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;With this option when a collision is found, the hash table will check to see if the next available index is empty, and if so it&amp;rsquo;ll place the data into that next index.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The rationale behind this technique is that because the hash table keys are typically quite distributed (e.g. they&amp;rsquo;re rarely sequential 0, 1, 2, 3, 4), then it&amp;rsquo;s likely that you&amp;rsquo;ll have many empty empty elements and you can use that empty space to store your colliding data.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Linear Probing is suggested over Separate Chaining if your data structure is expected to be quite large.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Personally I don&amp;rsquo;t like the idea of the Linear Probing technique as it feels like it&amp;rsquo;ll introduce more complexity and bugs. Also, there is a problem with this technique which is that it relies on the top level data structure being an array. Which is fine if the key we&amp;rsquo;re constructing is numerical, but if you want to have strings for your keys then that wont work very well and so you&amp;rsquo;ll need to be clever with how you implement this.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;graph&#34;&gt;Graph&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A graph is an abstract data type intended to guide the implementation of a data structure following the principles of &lt;a href=&#34;https://en.wikipedia.org/wiki/Graph_theory&#34; target=&#34;_blank&#34;&gt;graph theory&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The data struture itself is non-linear and it consists of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;nodes&lt;/strong&gt;: points on the graph (also known as &amp;lsquo;vertices&amp;rsquo;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;edges&lt;/strong&gt;: lines connecting each node.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The following image demonstrates a &amp;lsquo;directed&amp;rsquo; graph (notice the edges have arrows indicating the direction and flow):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/graph-directed.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/graph-directed.png&#34; alt=&#34;graph directed&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;an &amp;lsquo;undirected&amp;rsquo; graph simply has no arrow heads, so the flow between nodes can go in either direction.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Some graphs are &amp;lsquo;weighted&amp;rsquo; which means each &amp;lsquo;edge&amp;rsquo; has a numerical attribute assigned to them. These weights can indicate a stronger preference for a particular flow of direction.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Graphs are used for representing networks (both real and electronic), such as streets on a map or friends on Facebook.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When it comes to searching a graph, there are two methods:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Breadth First Search: look at siblings.&lt;/li&gt;&#xA;&lt;li&gt;Depth First Search: look at children.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Which approach you choose depends on the type of values you&amp;rsquo;re searching for. For example, relationship across fields would lend itself to BFS, whereas hierarchical tree searches would be better suited to DFS.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The discussion of data structures (and the various high-level data types) in computing is a massive topic, and so we cannot hope to try and cover every aspect and detail due to the sheer broad scope.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That said, I hope you found some useful insights and are now able to look at your programming language of choice with a slightly clearer understanding of the possible structures that sit beneath the abstraction surface.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/data-types-and-data-structures/</guid>
      <link>https://www.integralist.co.uk/posts/data-types-and-data-structures/</link>
      <pubDate>Wed, 30 Jan 2019 00:00:00 +0000</pubDate>
      <title>Data Types and Data Structures</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post is going to cover a few tools and features I plan on using when writing Python code in 2019.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† read my post &amp;ldquo;&lt;a href=&#34;/posts/python-app-dependencies/&#34;&gt;Python Management and Project Dependencies&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;type-hints-and-static-analysis&#34;&gt;Type Hints and Static Analysis&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some languages are weakly typed (JavaScript), some are strongly typed (Python) and some are statically typed (Go, Rust). Being &lt;em&gt;strongly&lt;/em&gt; typed means you can&amp;rsquo;t perform operations inappropriate to the type. For example, in Python you can&amp;rsquo;t add a number typed variable with a string typed variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Python 3.5 we get &amp;lsquo;type hints&amp;rsquo; which are a way of annotating Python code with type information in a bid to allow for external tools to provide safety similar to what you might see with a &lt;em&gt;statically&lt;/em&gt; typed language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Python actually ignores these annotations so type hints won&amp;rsquo;t break your code if you specify one expected type but provide a different one at runtime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following code snippet, which uses type hint annotations to indicate the types for both a function&amp;rsquo;s parameters as well as the function&amp;rsquo;s return value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def foo(n: int) -&amp;gt; str:&#xA;    print(f&#39;integer: {n}&#39;)&#xA;    return n&#xA;&#xA;foo(&#39;not an integer&#39;)  # prints &#39;integer: not an integer&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see that the code is stating we expect our &lt;code&gt;foo&lt;/code&gt; function to receive a parameter of type integer but when the function is called it&amp;rsquo;s actually passed a string. You&amp;rsquo;ll find this incorrect argument type &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; going to break your program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our example code also expects a string to be returned by the &lt;code&gt;foo&lt;/code&gt; function, but we return an integer value. So this also doesn&amp;rsquo;t break our program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you did nothing else at this point, your code would at the very least be very descriptive of the expectations for its use, but what these type hints afford us is the ability to use external tools for handling static analysis.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The most popular tool currently is called &amp;lsquo;&lt;a href=&#34;http://mypy-lang.org/&#34; target=&#34;_blank&#34;&gt;mypy&lt;/a&gt;&amp;rsquo;. You can run mypy via the command line, and it also provides integrated support for most code editors. This means you can catch yourself breaking the expectations of your program when writing/editing code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Type hints by themselves are quite basic and don&amp;rsquo;t offer much additional contextual information, so Python added a new &lt;a href=&#34;https://docs.python.org/3/library/typing.html&#34; target=&#34;_blank&#34;&gt;typing module&lt;/a&gt; to allow for more contextual annotations. One nice feature provided by this typing module is the ability to alias types. The following example is copied verbatim from the Python documentation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from typing import Dict, Tuple, List&#xA;&#xA;ConnectionOptions = Dict[str, str]&#xA;Address = Tuple[str, int]&#xA;Server = Tuple[Address, ConnectionOptions]&#xA;&#xA;def broadcast_message(message: str, servers: List[Server]) -&amp;gt; None:&#xA;    ...&#xA;&#xA;# The static type checker will treat the previous type signature as&#xA;# being exactly equivalent to this one.&#xA;def broadcast_message(&#xA;        message: str,&#xA;        servers: List[Tuple[Tuple[str, int], Dict[str, str]]]) -&amp;gt; None:&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I intend to use type hints a lot more in 2019 to help me both identify potential issues in my code during development, as well as being a means of code clarity as to what input/output types are expected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For more examples of using the typing module, please refer to either the official documentation or this useful &lt;a href=&#34;https://code.tutsplus.com/tutorials/python-3-type-hints-and-static-analysis--cms-25731&#34; target=&#34;_blank&#34;&gt;tutsplus.com article&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;interfaces-protocols-and-abstract-methods&#34;&gt;Interfaces, Protocols and Abstract Methods&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In the field of programming there are two concepts that can be a bit confusing to understand:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;interfaces&lt;/li&gt;&#xA;&lt;li&gt;abstract classes/methods&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll cover both of these in the following sections, along with Python&amp;rsquo;s own &amp;lsquo;protocols&amp;rsquo; and &amp;lsquo;abstract base classes&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In summary: an interface is a contract that defines &amp;lsquo;behaviour&amp;rsquo;, but has no &lt;em&gt;implementation&lt;/em&gt;. An abstract class is an actual class that can define common behaviour (including its implementation) along with &lt;em&gt;abstract&lt;/em&gt; methods that have no implementation. The implementation of the abstract methods will be defined by the subclass.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;interfaces&#34;&gt;Interfaces&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An interface is useful for when you don&amp;rsquo;t necessarily care for a specific concrete implementation of some functionality and will happily accept any object as long as it abides by the behavioural contract your receiver requires.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the specific use case of interfaces Python has traditionally relied on &amp;lsquo;duck typing&amp;rsquo;, which is where a caller provides an object and the receiver will attempt to call the appropriate method on the object (thus trusting the object has a corresponding method available).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is where the term duck typing comes from &amp;ldquo;If it walks like a duck and it quacks like a duck, then it must be a duck&amp;rdquo;. If the provided object has the expected method exposed, then we presume it&amp;rsquo;s of a suitable type.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In some cases, such as a reusable shared library, it might be preferable to write code defensibly. Meaning you verify the provided object has the interface the receiver is expecting. This is demonstrated in the following example which expects a &lt;code&gt;client&lt;/code&gt; object to be provided, and that object needs to be a HTTP client and so must have both a &lt;code&gt;get&lt;/code&gt; and a &lt;code&gt;post&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We could trust the caller has read the documentation and provided an appropriate object, but we don&amp;rsquo;t want to rely on that, so we manually defend against that failure scenario in our code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;async def execute_fetch(client, endpoint):&#xA;    &amp;quot;&amp;quot;&amp;quot;Make asynchronous requests via given http client.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    if invalid_client_interface(client):&#xA;        raise tornado.web.HTTPError(500, reason=&amp;quot;Invalid HTTP Client&amp;quot;)&#xA;&#xA;    ...&#xA;&#xA;def invalid_client_interface(client):&#xA;    &amp;quot;&amp;quot;&amp;quot;Ensure http client has supported interface.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    if hasattr(client, &#39;post&#39;) and hasattr(client, &#39;get&#39;):&#xA;        return False&#xA;    return True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Python not being a statically typed language means it has no support for traditional &amp;lsquo;interfaces&amp;rsquo; but the above example &amp;lsquo;defensive&amp;rsquo; code is a way to manually mimic it at runtime (as we have no means to validate this at any other time as there is no compilation step with Python, being it&amp;rsquo;s a dynamic language).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;protocols&#34;&gt;Protocols&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Python provides &amp;lsquo;&lt;a href=&#34;https://docs.python.org/3.7/library/collections.abc.html#module-collections.abc&#34; target=&#34;_blank&#34;&gt;protocols&lt;/a&gt;&amp;rsquo; as part of their &amp;lsquo;collections&amp;rsquo; module, which are also homed alongside another concept in Python called &amp;lsquo;abstract base classes&amp;rsquo; (this is something we&amp;rsquo;ll look at shortly as ABC&amp;rsquo;s are designed to play nicely with protocols).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Protocols are similar in spirit to interfaces in other languages, but in practice act more like &lt;em&gt;guidelines&lt;/em&gt; (this is because Python is a dynamic language and so strictly speaking it isn&amp;rsquo;t able to validate code correctness because there&amp;rsquo;s no compilation step with Python).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence a protocol &lt;em&gt;is&lt;/em&gt; an interface (it defines expected behaviours), while Python&amp;rsquo;s &amp;lsquo;Abstract Base Classes&amp;rsquo; provide a way to offer a form of runtime safety for the interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But to understand &amp;lsquo;protocols&amp;rsquo; and how we can utilize either MyPy or Abstract Base Classes with them, you&amp;rsquo;ll need to know a bit about &amp;lsquo;magic methods&amp;rsquo; in Python&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Magic Methods&lt;/strong&gt;:&lt;br&gt;&#xA;If one of your custom defined objects implements specific &lt;a href=&#34;https://rszalski.github.io/magicmethods/&#34; target=&#34;_blank&#34;&gt;&amp;lsquo;magic&amp;rsquo; methods&lt;/a&gt; (e.g. &lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__del__&lt;/code&gt; etc), then you&amp;rsquo;ll find a selection of builtin Python functions become available to use on those objects that otherwise those builtin functions wouldn&amp;rsquo;t necessarily support.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if we implement the &lt;code&gt;__len__&lt;/code&gt; magic method, then our object will be able to utilise the builtin &lt;code&gt;len&lt;/code&gt; function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we utilize protocols, then we can use mypy along with type hinting to implement a development time interface check.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following code snippet:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Team:&#xA;    def __init__(self, members):&#xA;        self.members = members&#xA;&#xA;t = Team([&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;])&#xA;&#xA;t.members  # [&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;]&#xA;&#xA;len(t)  # TypeError: object of type &#39;Team&#39; has no len()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This code doesn&amp;rsquo;t work because the &lt;code&gt;len&lt;/code&gt; function provided by the Python standard library doesn&amp;rsquo;t work on custom classes &lt;em&gt;unless&lt;/em&gt; the class defines a &lt;code&gt;__len__&lt;/code&gt; magic method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we add a &lt;code&gt;__len__&lt;/code&gt; method to the above example (see below), then we would find the &lt;code&gt;Team&lt;/code&gt; class now supports the &lt;a href=&#34;https://docs.python.org/3.7/library/collections.abc.html#collections.abc.Sized&#34; target=&#34;_blank&#34;&gt;collections.abc.Sized protocol&lt;/a&gt; and so the &lt;code&gt;len&lt;/code&gt; function will be able to work when given an instance of &lt;code&gt;Team&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Team:&#xA;    def __init__(self, members):&#xA;        self.members = members&#xA;&#xA;    def __len__(self):&#xA;        return len(self.members)&#xA;&#xA;t = Team([&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;])&#xA;&#xA;t.members  # [&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;]&#xA;&#xA;len(t)  # 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if we want to utilise mypy to help verifying our code at development time, let&amp;rsquo;s say we have a function that we want to accept any argument type that supports the &lt;code&gt;len&lt;/code&gt; function (i.e. anything that supports the &lt;code&gt;collections.abc.Sized&lt;/code&gt; protocol), then we can do so using the &lt;code&gt;typing.Sized&lt;/code&gt; type (see below example which adds such a function called &lt;code&gt;print_size&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import typing&#xA;&#xA;&#xA;class Team:&#xA;    def __init__(self, members):&#xA;        self.members = members&#xA;&#xA;    def __len__(self):&#xA;        return len(self.members)&#xA;&#xA;&#xA;t = Team([&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;])&#xA;&#xA;&#xA;def print_size(s: typing.Sized):&#xA;    print(len(s))&#xA;&#xA;&#xA;print_size(t)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that in the above example we state that the first argument to &lt;code&gt;print_size&lt;/code&gt; should be a type of the &lt;code&gt;typing.Sized&lt;/code&gt;, which is actually a mapping to the &lt;code&gt;collections.abc.Sized&lt;/code&gt; protocol.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we use the mypy static analysis tool as part of our application testing process (e.g. we only deploy the code if mypy is happy), then we can feel confident our code will be safe.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because if we were ever to change the code in a way where we were passing something to &lt;code&gt;print_size&lt;/code&gt; that &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; support calling &lt;code&gt;len()&lt;/code&gt; on it, then the mypy analysis would fail.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Custom Protocols&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Python typing module also let&amp;rsquo;s you define your own protocols using &lt;code&gt;typing.NewType&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at a simple example first to understand the use of &lt;code&gt;NewType&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from typing import NewType&#xA;&#xA;I = NewType(&#39;I&#39;, int)&#xA;&#xA;def foo() -&amp;gt; I:&#xA;   return I(123)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice a few things in the above example:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;the first argument to &lt;code&gt;typing.NewType&lt;/code&gt; needs to match the name of the variable it is assigned to.&lt;/li&gt;&#xA;&lt;li&gt;we can&amp;rsquo;t just return an integer, it needs to be casted to the new type &lt;code&gt;I&lt;/code&gt; first.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Now we have a basic understanding of &lt;code&gt;NewType&lt;/code&gt; let&amp;rsquo;s consider the following example where we create a new custom protocol called &lt;code&gt;CustomProtocol&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import typing&#xA;&#xA;&#xA;class Team:&#xA;    def __init__(self, members):&#xA;        self.members = members&#xA;&#xA;    def __len__(self):&#xA;        return len(self.members)&#xA;&#xA;&#xA;t = Team([&#39;foo&#39;, &#39;bar&#39;, &#39;baz&#39;])&#xA;&#xA;&#xA;def print_size(s: typing.Sized):&#xA;    print(len(s))&#xA;&#xA;&#xA;print_size(t)  # prints &#39;3&#39;&#xA;&#xA;CustomProtocol = typing.NewType(&#39;CustomProtocol&#39;, Team)&#xA;&#xA;cp = CustomProtocol(Team([&#39;beep&#39;, &#39;boop&#39;]))  # &amp;lt;class &#39;__main__.Team&#39;&amp;gt;&#xA;&#xA;print_size(cp)  # prints &#39;2&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when we create an instance of &lt;code&gt;CustomProtocol&lt;/code&gt; the underlying &amp;lsquo;type&amp;rsquo; is &lt;code&gt;Team&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The mypy static analysis tool can subsequently be used to verify code for both native protocols &lt;em&gt;and&lt;/em&gt; custom protocols, like so (see the type hint annotation added to the &lt;code&gt;print_size&lt;/code&gt; function, which mypy is happy with):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Team:&#xA;    def __init__(self, members):&#xA;        self.members = members&#xA;&#xA;    def __len__(self):&#xA;        return len(self.members)&#xA;&#xA;&#xA;CustomProtocol = typing.NewType(&#39;CustomProtocol&#39;, Team)&#xA;&#xA;&#xA;def print_size(s: CustomProtocol):  # we could also set type to `Team` &#xA;    print(len(s))  # prints &#39;2&#39;&#xA;&#xA;&#xA;cp = CustomProtocol(Team([&#39;beep&#39;, &#39;boop&#39;]))&#xA;&#xA;print_size(cp)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the argument type passed to &lt;code&gt;print_size&lt;/code&gt; is &lt;code&gt;CustomProtocol&lt;/code&gt; which doesn&amp;rsquo;t make mypy complain because the underlying type for &lt;code&gt;CustomProtocol&lt;/code&gt; is actually the &lt;code&gt;Team&lt;/code&gt; class, and the underlying &lt;code&gt;Team&lt;/code&gt; class is supporting the &lt;code&gt;typing.Sized&lt;/code&gt; interface (which maps to the &lt;code&gt;collections.abc.Sized&lt;/code&gt; protocol).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you want more information on mypy&amp;rsquo;s support of protocols, I suggest reading their &lt;a href=&#34;https://mypy.readthedocs.io/en/latest/protocols.html&#34; target=&#34;_blank&#34;&gt;specific documentation here&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;abstract-classes-methods&#34;&gt;Abstract Classes/Methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An abstract class allows you to define common behaviour as well as &amp;lsquo;abstract methods&amp;rsquo; that have no implementation, in which the subclass will be required to provide the implementation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can mimic that concept in Python using standard classes along with the classic &lt;a href=&#34;https://en.wikipedia.org/wiki/Template_method_pattern&#34; target=&#34;_blank&#34;&gt;&amp;lsquo;template method&amp;rsquo; pattern&lt;/a&gt; as shown in the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class MyAbstractClass:&#xA;    def common(self):&#xA;        print(&#39;common behaviour&#39;)&#xA;&#xA;    def MyAbstractMethod(self):&#xA;        raise NotImplementedError&#xA;&#xA;class Foo(MyAbstractClass):&#xA;    def MyAbstractMethod(self):&#xA;        print(&#39;do something&#39;)&#xA;&#xA;class Bar(MyAbstractClass):&#xA;    pass&#xA;&#xA;f = Foo()&#xA;f.common()  # prints &#39;common behaviour&#39;&#xA;f.MyAbstractMethod()  # prints &#39;do something&#39;&#xA;&#xA;b = Bar()&#xA;b.common()  # prints &#39;common behaviour&#39;&#xA;b.MyAbstractMethod()  # raises NotImplementedError&#xA;&#xA;o = MyAbstractClass()  # not possible in other languages (see note below)&#xA;o.common()  # prints &#39;common behaviour&#39;&#xA;o.MyAbstractMethod()  # raises NotImplementedError&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in other languages that support proper abstract classes, you would not be able to instantiate the abstract class directly (like we have done in our example).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Luckily Python does also provide us with what it refers to as &amp;lsquo;Abstract Base Classes&amp;rsquo; (here in referred to as ABC&amp;rsquo;s) which are a form of traditional abstract class, so there&amp;rsquo;s no need to necessarily mimic the behaviour like in our earlier example. See the following example that demonstrates this feature:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import abc&#xA;&#xA;class Foo(abc.ABC):&#xA;    @abc.abstractmethod&#xA;    def bar(self):&#xA;        pass&#xA;        &#xA;class Thing(Foo):&#xA;    pass&#xA;    &#xA;t = Thing()  # TypeError: Can&#39;t instantiate abstract class Thing with abstract methods bar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make the above example code work correctly we need our class &lt;code&gt;Thing&lt;/code&gt; to actually implement the exepected behaviour (i.e. a &lt;code&gt;bar&lt;/code&gt; method). If &lt;code&gt;Thing&lt;/code&gt; doesn&amp;rsquo;t provide the expected behaviour then we can&amp;rsquo;t instantiate a subclass of &lt;code&gt;Foo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This also means that if we&amp;rsquo;re using a static analysis tool such as mypy, we could have a receiver state it expects a type of &lt;code&gt;Thing&lt;/code&gt; and know more confidently that &lt;code&gt;Thing&lt;/code&gt; will definitely provide the behaviour we need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to understand that the use of an abstract class is subtly different to the use of traditional interfaces in that an interface doesn&amp;rsquo;t rely on a concrete implemention.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, our &lt;code&gt;Thing&lt;/code&gt; class is a &lt;em&gt;concrete&lt;/em&gt; implementation, and so we can&amp;rsquo;t provide the receiver with a &lt;em&gt;different&lt;/em&gt; class (even if the other class also happened to inherit from &lt;code&gt;Foo&lt;/code&gt;) as it won&amp;rsquo;t be equivalent to a &lt;code&gt;Thing&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the mypy docs have &lt;a href=&#34;https://mypy.readthedocs.io/en/latest/kinds_of_types.html#the-type-of-class-objects&#34; target=&#34;_blank&#34;&gt;a good detailed breakdown&lt;/a&gt; of how to indicate a dependency of a specific class type.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;dependency-management-with-pipenv&#34;&gt;Dependency Management (with pipenv)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;UPDATE 2019.12.20&lt;/strong&gt;: I no longer use Pipenv (as per below). I&amp;rsquo;ve written an updated version of how best to handle dependencies &lt;a href=&#34;/posts/python-app-dependencies/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Python has historically utilised a &lt;code&gt;requirements.txt&lt;/code&gt; file for defining the dependencies required of your program, but there are &lt;a href=&#34;https://medium.com/knerd/the-nine-circles-of-python-dependency-hell-481d53e3e025&#34; target=&#34;_blank&#34;&gt;various&lt;/a&gt; annoying &lt;a href=&#34;https://realpython.com/pipenv-guide/#dependency-management-with-requirementstxt&#34; target=&#34;_blank&#34;&gt;complications&lt;/a&gt; that go along with the traditional model of handling dependencies which has meant we have a few new players in the field to help us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One such concern is the setting up of multiple virtual environments for the various projects we need to work on:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;center&gt;&#xA;  &lt;a href=&#34;/assets/img/python-env.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/python-env.png&#34; alt=&#34;python env&#34; /&gt;&lt;/a&gt;&#xA;&lt;/center&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;center class=&#34;image-caption&#34;&gt;&lt;em&gt;XKCD: right as always&lt;/em&gt;&lt;/center&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here are the various alternatives we have to play with in 2019:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/ofek/hatch&#34; target=&#34;_blank&#34;&gt;Hatch&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/sdispater/poetry&#34; target=&#34;_blank&#34;&gt;Poetry&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/pypa/pipenv&#34; target=&#34;_blank&#34;&gt;Pipenv&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll be showing you the last tool in the list: &lt;strong&gt;Pipenv&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although &lt;em&gt;another&lt;/em&gt; alternative approach to the specific problem of virtual environments is to utilise docker containers for doing your development, but you&amp;rsquo;ll need to be comfortable using a terminal editor like Vim (unless you want to jump through some X11 hoops). Using containers also doesn&amp;rsquo;t eliminate the other issues with determining the right dependencies, so keep reading anyway.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if using Docker with a terminal editor like Vim to solve this problem sounds like a good approach for you, then review &lt;a href=&#34;/posts/docker-nginx/&#34;&gt;an older post of mine that explains how to do that&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here are the commands necessary to install Pipenv on macOS:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;brew install pyenv&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pip install pipenv&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll need &lt;a href=&#34;https://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt; to install the &lt;a href=&#34;https://github.com/pyenv/pyenv&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; command (a sub dependency) using &lt;code&gt;brew&lt;/code&gt;, and macOS should have Python 2.7.x installed by default so you should have the &lt;code&gt;pip&lt;/code&gt; command available already.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here are my quick steps for setting up a new project with Pipenv:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;mkdir foobar &amp;amp;&amp;amp; cd foobar&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pipenv --python 3.7&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;use &lt;code&gt;pyenv install --list&lt;/code&gt; to find out what Python versions are available to install.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now when working on a Pipenv project:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cd foobar&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pipenv shell&lt;/code&gt; or &lt;code&gt;pipenv run python ./app.py&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;use the &lt;code&gt;shell&lt;/code&gt; subcommand to have your current terminal permanently use the chosen Python version (e.g. &lt;code&gt;python ./app.py&lt;/code&gt; will work as if the current Python version is what you&amp;rsquo;ve defined), otherwise use the &lt;code&gt;run&lt;/code&gt; subcommand to execute the given command (e.g. &lt;code&gt;python ./app.py&lt;/code&gt;) within the chosen Python version temporarily.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You can now install dependencies specifically for the project&amp;rsquo;s specific Python environment:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;pipenv install tornado==5.0.2&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pipenv install --dev mypy tox flake8&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you have an existing &lt;code&gt;requirements.txt&lt;/code&gt; file, then you can generate a Pipfile from that using &lt;code&gt;pipenv install -r requirements.txt&lt;/code&gt;, alternatively if you need to do the reverse (generate a requirements from a Pipfile): &lt;code&gt;pipenv lock --requirements&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now none of these new tools are perfect, and if you want a good run down of one engineer&amp;rsquo;s perspective on them, &lt;a href=&#34;https://chriswarrick.com/blog/2018/07/17/pipenv-promises-a-lot-delivers-very-little/&#34; target=&#34;_blank&#34;&gt;read here&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it. We&amp;rsquo;ve looked at how to handle dependencies with Pipenv, and how to utilise static analysis tool mypy along with type hinting to give us more confidence in our code (as well as having the code become clearer intent).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly we looked at how to utilise interfaces and abstract classes to help improve the structure and safety of our code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Along with new additions to the &lt;code&gt;asyncio&lt;/code&gt; module (a simpler api for a start) and cleaner abstractions such as the new &lt;a href=&#34;https://realpython.com/python-data-classes/&#34; target=&#34;_blank&#34;&gt;data classes&lt;/a&gt; features, the future of Python hasn&amp;rsquo;t looked brighter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/design-python/</guid>
      <link>https://www.integralist.co.uk/posts/design-python/</link>
      <pubDate>Wed, 02 Jan 2019 00:00:00 +0000</pubDate>
      <title>Python Code Design and Dependency Management</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post will explain how to set-up and configure the various tooling necessary in order to be able to write cross-compatible modern (ES2015+) JavaScript code.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re unsure of what &amp;lsquo;modern&amp;rsquo; JavaScript looks like, then I&amp;rsquo;ll refer you to &lt;a href=&#34;http://kangax.github.io/compat-table/es6/&#34; target=&#34;_blank&#34;&gt;these compatibility tables&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The tools we&amp;rsquo;ll be using:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://babeljs.io/&#34; target=&#34;_blank&#34;&gt;Babel&lt;/a&gt;: transpiler of modern JS into ES5 compatible code.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://webpack.github.io/&#34; target=&#34;_blank&#34;&gt;Webpack&lt;/a&gt;: a js module bundler.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;webpack is actually capable of transforming, bundling, packaging just about anything (as we&amp;rsquo;ll see shortly).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To clarify, you don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; &amp;lsquo;webpack&amp;rsquo;, as babel handles transpiling modern JS code into ES5 compatible code, but it makes sense to use webpack still as a way to help with the performance of your client-side services.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind the configuration I&amp;rsquo;ll be describing will be using webpack primarily, and under that I&amp;rsquo;ll be using webpack &amp;lsquo;loaders&amp;rsquo; to utilise the babel transpiler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you weren&amp;rsquo;t using webpack, the configuration would be different as you&amp;rsquo;d be configuring babel directly instead of webpack.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;example-project&#34;&gt;Example Project&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re going to create a very basic project. It&amp;rsquo;s so basic, it doesn&amp;rsquo;t really do anything. It&amp;rsquo;s the bare minimum required in order to demonstrate the setup and configuration of webpack and babel (I purposely did this because learning new tech can be confusing enough without needing to understand a real-world application at the same time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing you&amp;rsquo;ll need upfront though, is &lt;a href=&#34;https://nodejs.org/&#34; target=&#34;_blank&#34;&gt;Node&lt;/a&gt; and &lt;a href=&#34;https://www.npmjs.com/&#34; target=&#34;_blank&#34;&gt;NPM&lt;/a&gt; installed, as we&amp;rsquo;ll be installing webpack and babel from existing NPM packages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s begin by creating our project directory:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;mkdir modern-js &amp;amp;&amp;amp; cd modern-js&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I will be working exclusively from the terminal.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now create an empty &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;npm init -y&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next, we&amp;rsquo;ll install all the relevant packages we&amp;rsquo;ll be needing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;npm install --save-dev webpack \&#xA;                       webpack-cli \&#xA;                       webpack-dev-server \&#xA;                       @babel/core \&#xA;                       @babel/preset-env \&#xA;                       &amp;quot;babel-loader@^8.0.0-beta&amp;quot; \&#xA;                       style-loader \&#xA;                       css-loader \&#xA;                       sass-loader \&#xA;                       node-sass \&#xA;                       eslint@4.x babel-eslint@8&#xA;&#xA;npm install --save @babel/polyfill&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the dev dependencies need to be installed in the order they&amp;rsquo;re specified above, otherwise npm will complain/fail.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Your &lt;code&gt;package.json&lt;/code&gt; should now have the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  &amp;quot;name&amp;quot;: &amp;quot;modern-js&amp;quot;,&#xA;  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,&#xA;  &amp;quot;description&amp;quot;: &amp;quot;&amp;quot;,&#xA;  &amp;quot;main&amp;quot;: &amp;quot;index.js&amp;quot;,&#xA;  &amp;quot;scripts&amp;quot;: {&#xA;    &amp;quot;test&amp;quot;: &amp;quot;echo \&amp;quot;Error: no test specified\&amp;quot; &amp;amp;&amp;amp; exit 1&amp;quot;&#xA;  },&#xA;  &amp;quot;keywords&amp;quot;: [],&#xA;  &amp;quot;author&amp;quot;: &amp;quot;&amp;quot;,&#xA;  &amp;quot;license&amp;quot;: &amp;quot;ISC&amp;quot;,&#xA;  &amp;quot;devDependencies&amp;quot;: {&#xA;    &amp;quot;@babel/core&amp;quot;: &amp;quot;^7.1.2&amp;quot;,&#xA;    &amp;quot;@babel/preset-env&amp;quot;: &amp;quot;^7.1.0&amp;quot;,&#xA;    &amp;quot;babel-eslint&amp;quot;: &amp;quot;^8.2.6&amp;quot;,&#xA;    &amp;quot;babel-loader&amp;quot;: &amp;quot;^8.0.4&amp;quot;,&#xA;    &amp;quot;css-loader&amp;quot;: &amp;quot;^1.0.0&amp;quot;,&#xA;    &amp;quot;eslint&amp;quot;: &amp;quot;^4.19.1&amp;quot;,&#xA;    &amp;quot;node-sass&amp;quot;: &amp;quot;^4.9.3&amp;quot;,&#xA;    &amp;quot;sass-loader&amp;quot;: &amp;quot;^7.1.0&amp;quot;,&#xA;    &amp;quot;style-loader&amp;quot;: &amp;quot;^0.23.0&amp;quot;,&#xA;    &amp;quot;webpack&amp;quot;: &amp;quot;^4.20.2&amp;quot;,&#xA;    &amp;quot;webpack-cli&amp;quot;: &amp;quot;^3.1.2&amp;quot;,&#xA;    &amp;quot;webpack-dev-server&amp;quot;: &amp;quot;^3.1.9&amp;quot;&#xA;  },&#xA;  &amp;quot;dependencies&amp;quot;: {&#xA;    &amp;quot;@babel/polyfill&amp;quot;: &amp;quot;^7.0.0&amp;quot;&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are two important Babel related packages to pay attention to&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;@babel/polyfill&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@babel/present-env&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://babeljs.io/docs/en/babel-polyfill&#34; target=&#34;_blank&#34;&gt;@babel/polyfill&lt;/a&gt; dependency will help emulate a full ES2015+ environment, and this means you can use new built-ins like &lt;code&gt;Promise&lt;/code&gt; or &lt;code&gt;WeakMap&lt;/code&gt;, static methods like &lt;code&gt;Array.from&lt;/code&gt; or &lt;code&gt;Object.assign&lt;/code&gt;, instance methods like &lt;code&gt;Array.prototype.includes&lt;/code&gt; (amongst others, see the documentation for more information).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://babeljs.io/docs/en/babel-preset-env&#34; target=&#34;_blank&#34;&gt;@babel/preset-env&lt;/a&gt; helps manage the browser environment for you, so it&amp;rsquo;ll handle determining what additional scripts/polyfills you need. By default it&amp;rsquo;ll setup everything to support ES5 environments, but you can configure it for very specific browsers if you don&amp;rsquo;t need to worry about older browsers.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;@babel/polyfill&lt;/code&gt; also provides a &lt;code&gt;useBuiltIns&lt;/code&gt; flag which allows Babel to selectively polyfill built-in features that were introduced as part of ES6+. Because it filters polyfills to include only the ones required by the environment, we mitigate the cost of shipping with babel-polyfill in its entirety.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s create all the files we need to build out our example application:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;mkdir src dist&#xA;touch .eslintrc src/index.js src/component.js src/styles.scss dist/index.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This should result in the following tree structure&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;tree -I node_modules&#xA;&#xA;.&#xA;├── .eslintrc&#xA;├── dist&#xA;│   └── index.html&#xA;├── src&#xA;│   ├── component.js&#xA;│   ├── index.js&#xA;│   └── styles.scss&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see we have one &lt;a href=&#34;https://sass-lang.com/&#34; target=&#34;_blank&#34;&gt;Sass&lt;/a&gt; file and two JavaScript files, as well as a single HTML page that will load our scripts/css.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now look at the contents of each of these files&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;eslintrc&#34;&gt;.eslintrc&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  &amp;quot;parser&amp;quot;: &amp;quot;babel-eslint&amp;quot;,&#xA;  &amp;quot;globals&amp;quot;: {&#xA;    &amp;quot;console&amp;quot;: true,&#xA;    &amp;quot;document&amp;quot;: true,&#xA;    &amp;quot;window&amp;quot;: true&#xA;  },&#xA;  &amp;quot;rules&amp;quot;: {&#xA;    &#39;brace-style&#39;: [2, &#39;1tbs&#39;, {&#39;allowSingleLine&#39;: true}],&#xA;    &#39;camelcase&#39;: 2,&#xA;    &#39;comma-spacing&#39;: 2,&#xA;    &#39;comma-style&#39;: 2,&#xA;    &#39;curly&#39;: 2,&#xA;    &#39;eol-last&#39;: 2,&#xA;    &#39;indent&#39;: [2, 2],&#xA;    &#39;key-spacing&#39;: 2,&#xA;    &#39;new-cap&#39;: 2,&#xA;    &#39;new-parens&#39;: 2,&#xA;    &#39;no-lonely-if&#39;: 2,&#xA;    &#39;no-multi-spaces&#39;: 2,&#xA;    &#39;no-multiple-empty-lines&#39;: [2, {&#39;max&#39;: 2}],&#xA;    &#39;func-call-spacing&#39;: 2,&#xA;    &#39;no-trailing-spaces&#39;: 2,&#xA;    &#39;quotes&#39;: [2, &#39;single&#39;, {&#39;allowTemplateLiterals&#39;: true}],&#xA;    &#39;semi&#39;: 2,&#xA;    &#39;semi-spacing&#39;: 2,&#xA;    &#39;space-before-blocks&#39;: 2,&#xA;    &#39;space-in-parens&#39;: 2,&#xA;    &#39;space-infix-ops&#39;: 2,&#xA;    &#39;space-unary-ops&#39;: 2,&#xA;    &#39;array-callback-return&#39;: 2,&#xA;    &#39;block-scoped-var&#39;: 2,&#xA;    &#39;consistent-return&#39;: 2,&#xA;    &#39;eqeqeq&#39;: 2,&#xA;    &#39;guard-for-in&#39;: 2,&#xA;    &#39;no-array-constructor&#39;: 2,&#xA;    &#39;no-caller&#39;: 2,&#xA;    &#39;no-cond-assign&#39;: 2,&#xA;    &#39;no-const-assign&#39;: 2,&#xA;    &#39;no-control-regex&#39;: 2,&#xA;    &#39;no-delete-var&#39;: 2,&#xA;    &#39;no-dupe-args&#39;: 2,&#xA;    &#39;no-dupe-class-members&#39;: 2,&#xA;    &#39;no-dupe-keys&#39;: 2,&#xA;    &#39;no-duplicate-case&#39;: 2,&#xA;    &#39;no-empty-character-class&#39;: 2,&#xA;    &#39;no-empty-pattern&#39;: 2,&#xA;    &#39;no-eval&#39;: 2,&#xA;    &#39;no-ex-assign&#39;: 2,&#xA;    &#39;no-extend-native&#39;: 2,&#xA;    &#39;no-extra-bind&#39;: 2,&#xA;    &#39;no-fallthrough&#39;: 2,&#xA;    &#39;no-func-assign&#39;: 2,&#xA;    &#39;no-implied-eval&#39;: 2,&#xA;    &#39;no-invalid-regexp&#39;: 2,&#xA;    &#39;no-iterator&#39;: 2,&#xA;    &#39;no-lone-blocks&#39;: 2,&#xA;    &#39;no-loop-func&#39;: 2,&#xA;    &#39;no-mixed-operators&#39;: [2, {&#xA;      groups: [&#xA;        [&#39;&amp;amp;&#39;, &#39;|&#39;, &#39;^&#39;, &#39;~&#39;, &#39;&amp;lt;&amp;lt;&#39;, &#39;&amp;gt;&amp;gt;&#39;, &#39;&amp;gt;&amp;gt;&amp;gt;&#39;],&#xA;        [&#39;==&#39;, &#39;!=&#39;, &#39;===&#39;, &#39;!==&#39;, &#39;&amp;gt;&#39;, &#39;&amp;gt;=&#39;, &#39;&amp;lt;&#39;, &#39;&amp;lt;=&#39;],&#xA;        [&#39;&amp;amp;&amp;amp;&#39;, &#39;||&#39;],&#xA;        [&#39;in&#39;, &#39;instanceof&#39;]&#xA;      ],&#xA;      allowSamePrecedence: false&#xA;    }],&#xA;    &#39;no-multi-str&#39;: 2,&#xA;    &#39;no-native-reassign&#39;: 2,&#xA;    &#39;no-unneeded-ternary&#39;: 2,&#xA;    &#39;no-unsafe-negation&#39;: 2,&#xA;    &#39;no-new-func&#39;: 2,&#xA;    &#39;no-new-object&#39;: 2,&#xA;    &#39;no-new-symbol&#39;: 2,&#xA;    &#39;no-new-wrappers&#39;: 2,&#xA;    &#39;no-obj-calls&#39;: 2,&#xA;    &#39;no-octal&#39;: 2,&#xA;    &#39;no-octal-escape&#39;: 2,&#xA;    &#39;no-redeclare&#39;: 2,&#xA;    &#39;no-regex-spaces&#39;: 2,&#xA;    &#39;no-script-url&#39;: 2,&#xA;    &#39;no-self-assign&#39;: 2,&#xA;    &#39;no-self-compare&#39;: 2,&#xA;    &#39;no-sequences&#39;: 2,&#xA;    &#39;no-shadow-restricted-names&#39;: 2,&#xA;    &#39;no-shadow&#39;: 2,&#xA;    &#39;no-sparse-arrays&#39;: 2,&#xA;    &#39;no-template-curly-in-string&#39;: 2,&#xA;    &#39;no-this-before-super&#39;: 2,&#xA;    &#39;no-throw-literal&#39;: 2,&#xA;    &#39;no-undef&#39;: 2,&#xA;    &#39;no-unexpected-multiline&#39;: 2,&#xA;    &#39;no-unreachable&#39;: 2,&#xA;    &#39;no-unused-expressions&#39;: [2, {&#xA;      &#39;allowShortCircuit&#39;: true,&#xA;      &#39;allowTernary&#39;: true&#xA;    }],&#xA;    &#39;no-unused-vars&#39;: 2,&#xA;    &#39;no-use-before-define&#39;: [2, &#39;nofunc&#39;],&#xA;    &#39;no-useless-computed-key&#39;: 2,&#xA;    &#39;no-useless-concat&#39;: 2,&#xA;    &#39;no-useless-constructor&#39;: 2,&#xA;    &#39;no-useless-escape&#39;: 2,&#xA;    &#39;no-useless-rename&#39;: 2,&#xA;    &#39;no-with&#39;: 2,&#xA;    &#39;radix&#39;: 2,&#xA;    &#39;require-yield&#39;: 2,&#xA;    &#39;use-isnan&#39;: 2,&#xA;    &#39;valid-typeof&#39;: 2,&#xA;    &#39;wrap-iife&#39;: [2, &#39;any&#39;]&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t have to worry too much about the contents of this file, as it&amp;rsquo;s just the configuration I&amp;rsquo;m using to define what is &amp;lsquo;good&amp;rsquo; JavaScript syntax.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In other words, if your code editor is configured properly, then any JS code you write that violates any of these ES linter values, will be flagged as an error.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dist-index-html&#34;&gt;dist/index.html&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;!doctype html&amp;gt;&#xA;&amp;lt;html&amp;gt;&#xA;  &amp;lt;head&amp;gt;&#xA;    &amp;lt;title&amp;gt;Hello Webpack&amp;lt;/title&amp;gt;&#xA;  &amp;lt;/head&amp;gt;&#xA;  &amp;lt;body&amp;gt;&#xA;    &amp;lt;script src=&amp;quot;bundle.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&#xA;  &amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is simple enough, a HTML page that loads a &lt;code&gt;bundle.js&lt;/code&gt; script (which currently doesn&amp;rsquo;t exist, and will be generated by webpack, &lt;em&gt;via&lt;/em&gt; babel).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;src-component-js&#34;&gt;src/component.js&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;const c = [&#39;x&#39;, &#39;y&#39;, &#39;z&#39;];&#xA;&#xA;export default c;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;A simple script that defines an Array of items and then exports them (using modern JS module syntax, familiar to people who may have written Node applications before).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;src-index-js&#34;&gt;src/index.js&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/*eslint no-undef: &amp;quot;error&amp;quot;*/&#xA;/*eslint-env browser*/&#xA;&#xA;import &#39;@babel/polyfill&#39;;&#xA;import &#39;./styles.scss&#39;;&#xA;import c from &#39;./component.js&#39;;&#xA;&#xA;console.log(c);&#xA;&#xA;let a = 1;&#xA;let b = 2;&#xA;[a, b] = [b, a];&#xA;console.log(a);&#xA;console.log(b);&#xA;&#xA;const root = document.createElement(&#39;div&#39;);&#xA;root.innerHTML = `&amp;lt;p&amp;gt;Hello Webpack!&amp;lt;/p&amp;gt;`;&#xA;document.body.appendChild(root);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;A simple script that imports from our &lt;code&gt;component.js&lt;/code&gt; and then logs it (to prove the import code works), it then demonstrates &lt;code&gt;let&lt;/code&gt; variables and another modern JS feature known as &amp;lsquo;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment&#34; target=&#34;_blank&#34;&gt;destructuring&lt;/a&gt;&amp;rsquo; before finally creating a HTML &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element and populating it with some text and inserting it into the DOM of the HTML page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At the top of the script you&amp;rsquo;ll notice some code comments. These are used to tell our ES linter package what context this script is running in, and so global references such as &lt;code&gt;document&lt;/code&gt; or &lt;code&gt;console&lt;/code&gt; won&amp;rsquo;t trigger a linting error as we&amp;rsquo;ve told the linter that the context the script will run is the browser environment, where those globals are expected to exist. The code comment for &lt;code&gt;eslint-env&lt;/code&gt; could be replaced by adding individual references into the &lt;code&gt;.eslintrc&lt;/code&gt; file (and I have done that, take a look at the &lt;code&gt;globals&lt;/code&gt; field in the file contents shown earlier), but I prefer the code comment as it can be a much clearer indicator of the expectations of the file&amp;rsquo;s scope.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also notice that we import the &lt;code&gt;@babel/polyfill&lt;/code&gt; at the top of the file. This module must &lt;em&gt;always&lt;/em&gt; be the first import in the file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, you&amp;rsquo;ll notice we also import a Sass file, which admittedly is a bit strange considering we&amp;rsquo;re dealing with a JS file, but we&amp;rsquo;ll dig into this a little bit more later on and why we do that.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;src-styles-scss&#34;&gt;src/styles.scss&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$color: blue;&#xA;&#xA;body {&#xA;  background-color: $color;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is a simple Sass file that demonstrates how to use a &amp;lsquo;variable&amp;rsquo; to generate dynamic CSS output (in this case, the body element should have a blue background).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;webpack-configuration&#34;&gt;Webpack Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, at this point we have a set of JS files that can&amp;rsquo;t be used in some browsers due to the fact that they use features not supported by most web browsers. So we want to compile this code down into something that &lt;em&gt;is&lt;/em&gt; understandable to most browsers (i.e. ES5 standardized code).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do that we&amp;rsquo;ll be using Babel (as our transpiler) and Webpack as our module bundler. Webpack will take the separate JS files and combine them into a single &lt;code&gt;bundle.js&lt;/code&gt; file, which our HTML will attempt to load.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s create a &lt;code&gt;webpack.config.js&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;touch webpack.config.js&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll then add the following contents to that file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/*eslint-env node*/&#xA;&#xA;const path = require(&#39;path&#39;);&#xA;&#xA;module.exports = {&#xA;  entry: &#39;./src/index.js&#39;,&#xA;  output: {&#xA;    filename: &#39;bundle.js&#39;,&#xA;    path: path.resolve(__dirname, &#39;dist&#39;),&#xA;    publicPath: &#39;/dist&#39;&#xA;  },&#xA;  module: {&#xA;    rules: [&#xA;      {&#xA;        test: /\.js$/,&#xA;        exclude: /(node_modules|bower_components)/,&#xA;        use: {&#xA;          loader: &#39;babel-loader&#39;,&#xA;        }&#xA;      },&#xA;      {&#xA;        test: /\.scss$/,&#xA;        use: [&#xA;          {loader: &#39;style-loader&#39;},&#xA;          {loader: &#39;css-loader&#39;},&#xA;          {loader: &#39;sass-loader&#39;}&#xA;        ]&#xA;      }&#xA;    ]&#xA;  }&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice a similar code comment at the top of the file, which again is for the benefit of our ES linter. In this case it won&amp;rsquo;t complain when it sees certain global references such as &lt;code&gt;require&lt;/code&gt; or &lt;code&gt;module&lt;/code&gt; (as we&amp;rsquo;ve told the linter that the context the script will be run in is the Node environment, where those globals are expected to exist).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We see the &lt;code&gt;entry&lt;/code&gt; field of the configuration is telling webpack that the main application JavaScript file is going to be found at &lt;code&gt;./src/index.js&lt;/code&gt;. Webpack will look at this file and then traverse back up its dependency tree looking for imports and it will combine each of those separate files into one single file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The file that is generated (and where) is determined by the &lt;code&gt;output&lt;/code&gt; field. We can see we want the file to be called &lt;code&gt;bundle.js&lt;/code&gt; and we want the file to be saved to the &lt;code&gt;./dist&lt;/code&gt; directory (this is indicated by the &lt;code&gt;path&lt;/code&gt; field).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;publicPath&lt;/code&gt; field is a bit different, in that it tells the &lt;code&gt;webpack-dev-server&lt;/code&gt; package where to find the &lt;code&gt;bundle.js&lt;/code&gt; file that the HTML is attempting to load. What won&amp;rsquo;t be clear yet is the fact that when running our code locally (in dev) we&amp;rsquo;ll be using &lt;code&gt;webpack-dev-server&lt;/code&gt; because it allows us to utilise a web server for running our code as well as &amp;lsquo;hot reloading&amp;rsquo; (which means, if we&amp;rsquo;re dealing with a complex single-page application with lots of nested state, that a change in code doesn&amp;rsquo;t cause us to lose the state the page is in).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For production we&amp;rsquo;ll statically generate our final bundle file using the standard &lt;code&gt;webpack&lt;/code&gt; command, and so you&amp;rsquo;ll see shortly that we need to update our &lt;code&gt;package.json&lt;/code&gt; to include two &lt;code&gt;npm run ...&lt;/code&gt; commands that let us use either &lt;code&gt;webpack-dev-server&lt;/code&gt; or &lt;code&gt;webpack&lt;/code&gt; depending on where our code needs to run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;module&lt;/code&gt; field tells webpack, that for every file it finds, before adding it to the final &lt;code&gt;bundle.js&lt;/code&gt;, to run it through a &amp;lsquo;loader&amp;rsquo; script for additional processing. In this case, all &lt;code&gt;.js&lt;/code&gt; files are passed through babel and so their modern JS code is transpiled into ES5 code first before being added to &lt;code&gt;bundle.js&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, we look for any Sass &lt;code&gt;.scss&lt;/code&gt; files and tell webpack to pass those files through multiple &amp;lsquo;loaders&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;sass-loader&lt;/strong&gt;: transforms Sass into CSS.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;css-loader&lt;/strong&gt;: parses the CSS into JavaScript and resolves any dependencies.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;style-loader&lt;/strong&gt;: outputs our CSS into a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag in the document.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Loaders are executed in a nested fashion, meaning the above order of loaders would evaluate to something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;styleLoader(cssLoader(sassLoader(&amp;quot;source&amp;quot;)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where the source file is passed into the Sass loader, and so transforming the Sass into CSS. That CSS is then passed into the CSS loader, which allows it to be parsed by JavaScript. Finally, the Style loader places our CSS into a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag within our HTML page.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;package-json-update&#34;&gt;Package.json Update&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As mentioned earlier, we want to modify the &lt;code&gt;package.json&lt;/code&gt; so that we have two &lt;code&gt;npm run ...&lt;/code&gt; commands for letting us run our code in development mode (i.e. locally) or compile our code ready for use in production.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following snippet shows the changes needed to be made:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  ...&#xA;&#xA;  &amp;quot;scripts&amp;quot;: {&#xA;    &amp;quot;build&amp;quot;: &amp;quot;webpack --mode=production&amp;quot;,&#xA;    &amp;quot;dev&amp;quot;: &amp;quot;webpack-dev-server --mode=development --config webpack.config.js&amp;quot;,&#xA;&#xA;    ...&#xA;  },&#xA;  &#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now we can run either &lt;code&gt;npm run dev&lt;/code&gt; (for local dev) or &lt;code&gt;npm run build&lt;/code&gt; (to compile our bundle for production).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that we pass a specific &lt;code&gt;--mode&lt;/code&gt; flag to both &lt;code&gt;webpack&lt;/code&gt; and &lt;code&gt;webpack-dev-server&lt;/code&gt;, and this indicates to both tools what to do to the files it&amp;rsquo;s configured to interact with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of &lt;code&gt;--mode=production&lt;/code&gt; the &lt;code&gt;webpack&lt;/code&gt; tool will make additional modifications that means the &lt;code&gt;bundle.js&lt;/code&gt; output is as efficient as possible (such as minifiying and obfuscating the code).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whereas &lt;code&gt;--mode=development&lt;/code&gt; will allow for the generation of webpack source map files (to aid you in debugging).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This should be the basics covered of how to use babel with webpack, and hopefully is enough to help you kickstart your exploration of new JavaScript features.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/js-modern/</guid>
      <link>https://www.integralist.co.uk/posts/js-modern/</link>
      <pubDate>Sat, 29 Sep 2018 00:00:00 +0000</pubDate>
      <title>Modern JavaScript: Webpack and Babel</title>
    </item>
    <item>
      <description>&lt;p&gt;You&amp;rsquo;re a software engineer with many years of technical experience, and you&amp;rsquo;ve decided you want to kickstart the process of working towards becoming an &amp;lsquo;Engineering Manager&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what do you need to know? Let&amp;rsquo;s discuss&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;roles&#34;&gt;Roles&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As a software engineer you have a few different paths available to you for career progression:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Senior Software Engineer&lt;/li&gt;&#xA;&lt;li&gt;Staff Software Engineer&lt;/li&gt;&#xA;&lt;li&gt;Principal Software Engineer&lt;/li&gt;&#xA;&lt;li&gt;Architect&lt;/li&gt;&#xA;&lt;li&gt;Tech Lead&lt;/li&gt;&#xA;&lt;li&gt;Engineering Manager&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the role hierarchy can change per organisation&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You may notice some of these roles are not like the others 😉 It&amp;rsquo;s worth recognizing that there is a slight separation between the last two roles (Tech Lead, Engineering Manager) and the rest of the roles, in that the last two are more closely related to management than the other roles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve grouped these roles together like this because they tend to be the progression path for a lot of engineers. They exhaust all possibilities as far as &amp;lsquo;engineering&amp;rsquo; as an IC (individual contributor) before finally residing themselves to a management role.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This doesn&amp;rsquo;t &lt;em&gt;have&lt;/em&gt; to be the case though. You might decide to make that shift to a more management role before progressing through the more senior engineering roles, but you may find some organisations will expect a certain level of engineering experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When moving up the career ladder you&amp;rsquo;ll typically find that between roles there is a fair amount of cross-over responsibilities, but for the purposes of this post let&amp;rsquo;s focus in on the last role (&amp;lsquo;Engineering Manager&amp;rsquo;) and what that entails.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;responsibilities&#34;&gt;Responsibilities&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below I have listed a few different areas of responsibility (as I see them) associated with an Engineering Manager role, and of course these responsibilities can change depending on the culture of where you work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning it&amp;rsquo;s a good idea, when interviewing for an Engineering Manager role, to ask clarifying questions in order to help you understand the expectations of that role (in the specific context of that organisation).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to learn more about &lt;em&gt;what&lt;/em&gt; to talk about during an interview, read my post &amp;lsquo;&lt;a href=&#34;/posts/interview-topics/&#34;&gt;Interview Topics&lt;/a&gt;&amp;rsquo;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;For example, some companies have dedicated &amp;lsquo;Project Managers&amp;rsquo;; meaning an Engineering Manager doesn&amp;rsquo;t have to worry too much with that aspect of the job, and can instead focus on technical leadership responsibilities.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another example is the role of a &amp;lsquo;Tech Lead&amp;rsquo;; some organisations use this name and &amp;lsquo;Engineering Manager&amp;rsquo; interchangeably, while others treat them as distinct roles (and in some cases a less management/more code oriented role than an Engineering Manager).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see also my post &amp;lsquo;&lt;a href=&#34;/posts/project-management/&#34;&gt;Project Management in Five Minutes&lt;/a&gt;&amp;rsquo; which discusses Lara Hogan&amp;rsquo;s venn diagram of various leadership roles, as well as a project management checklist.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;motivation&#34;&gt;Motivation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A good engineering manager must be committed to building great software, great teams, creativity, careers, and general welfare of the team members.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind, the following list feels like (to me) a reasonable breakdown of the various jobs you (as an Engineering Manager) will be expected to look after&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Team Leader&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1:1&amp;rsquo;s (read &lt;a href=&#34;/posts/a-guide-to-effective-1-1-meetings/&#34;&gt;my post on better 1:1 practices&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Mentoring&lt;/li&gt;&#xA;&lt;li&gt;Support&lt;/li&gt;&#xA;&lt;li&gt;Career development&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Technical Lead&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Define and communicate with non-technical stake holders&lt;/li&gt;&#xA;&lt;li&gt;Guide the architecture and technical design&lt;/li&gt;&#xA;&lt;li&gt;Resolve conflicts around technical discussions&lt;/li&gt;&#xA;&lt;li&gt;Write code and work with the engineering team&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Project Management&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Define technical requirements&lt;/li&gt;&#xA;&lt;li&gt;Work with non-technical stake holders to define user stories&lt;/li&gt;&#xA;&lt;li&gt;Breakdown large tasks into smaller tasks&lt;/li&gt;&#xA;&lt;li&gt;Prioritise work and revise priorities when necessary&lt;/li&gt;&#xA;&lt;li&gt;Establish schedules, estimates and milestone deliveries&lt;/li&gt;&#xA;&lt;li&gt;Run and guide the technical aspect of the project&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Communicator&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Up: team/project status and health to upper management&lt;/li&gt;&#xA;&lt;li&gt;Down: updates/decision making to your team and direct reports&lt;/li&gt;&#xA;&lt;li&gt;Across: identify, engage and collaborate with other teams&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Recruitment&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Work with recruiters to define required engineering roles&lt;/li&gt;&#xA;&lt;li&gt;Screen resumes&lt;/li&gt;&#xA;&lt;li&gt;Interview candidates&lt;/li&gt;&#xA;&lt;li&gt;Assist onboarding new recruits&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;communication&#34;&gt;Communication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The most important skill you&amp;rsquo;ll need, if you are to be effective as a manager of people (e.g. your direct reports, your managers, your stake holders: both technical and non-technical), is communication.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You need to be able to build strong and trusted relationships with these people. You need to be able to &lt;em&gt;challenge&lt;/em&gt; them and push them to do better, for &lt;em&gt;their&lt;/em&gt; own success, &lt;em&gt;not&lt;/em&gt; the business.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To elaborate further: helping people to reach their goals, to be happy and to help them find doing what they enjoy doing (while still challenging them) will ultimately yield better value from the work they do, and as a side-effect the business will benefit more greatly than if you push someone down another path designed with the business in mind.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means &lt;em&gt;caring personally&lt;/em&gt; about the people you are interacting with and doing what you can to bring out their best. It also means recognising when someone &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; a good fit for your team, and in extreme cases &amp;lsquo;letting them go&amp;rsquo; can actually work out better for both them and the business.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Patty McCord discusses this topic in-depth in her book on &lt;em&gt;culture building&lt;/em&gt; at scale &amp;ldquo;&lt;a href=&#34;http://pattymccord.com/book/&#34; target=&#34;_blank&#34;&gt;Powerful: building a culture of freedom and responsibility&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence let&amp;rsquo;s help people work on things that will realize their ambitions, but not at the expense of the business, more &lt;em&gt;in co-operation&lt;/em&gt; with the business. But if your ambitions don&amp;rsquo;t fit with the business, then maybe it&amp;rsquo;s best for you and the business to separate ways. I like that as a healthy way for both sides to either work together for a common good or separate ways for an equally better outcome.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When building relationships you should be mindful of not falling too heavily on one side or another with regards to &amp;lsquo;professional vs personal&amp;rsquo;. Find a balance, and if unsure err on the side of building a respected professional relationship, as friendship and a greater sense of personal appreciation/understanding (in some cases) will naturally occur.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below I&amp;rsquo;ve listed some useful resources for learning how to communicate effectively (these are all highly recommended):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.soundstrue.com/store/authentic-communication.html&#34; target=&#34;_blank&#34;&gt;Authentic Communication&lt;/a&gt; by Fred Kofman.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.radicalcandor.com/&#34; target=&#34;_blank&#34;&gt;Radical Candor&lt;/a&gt; by Kim Scott.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/24c8a9ce570d78d37ed0cf9967594e0e&#34; target=&#34;_blank&#34;&gt;SBI: Situation, Behaviour, Impact&lt;/a&gt; a methodology developed by The Center for Creative Leadership.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.amazon.co.uk/Hard-Thing-About-Things-Building/dp/0062273205/ref=asap_bc&#34; target=&#34;_blank&#34;&gt;The Hard Thing About Hard Things&lt;/a&gt; by Ben Horowitz.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&amp;lsquo;Authentic Communication&amp;rsquo; is actually taken from a larger work called &lt;a href=&#34;https://www.soundstrue.com/store/conscious-business-4036.html&#34; target=&#34;_blank&#34;&gt;Conscious Business: How to build value through values&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;team-leader&#34;&gt;Team Leader&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As someone who is going to be mentoring and supporting a team of engineers, it is important you understand the motivations and what drives your team. In doing so you&amp;rsquo;ll be better equipped to find them the right roles within the organisation that brings out their best work and allows them to grow in the areas that matter the most to them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also important to sometimes think as an &amp;lsquo;engineer&amp;rsquo; again. When you design and develop large scale systems you identify bottlenecks and ways of working that reduce complexity and support certain services to &lt;em&gt;scale&lt;/em&gt;. Now think about &lt;em&gt;that&lt;/em&gt; when you&amp;rsquo;re handling management duties.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Do you find yourself handling tasks, or using processes, that take up a lot of time? This might be ok for now while you&amp;rsquo;re responsible for a small team but how will that work out for you once you start taking on &lt;em&gt;more&lt;/em&gt; teams and more responsibilities? Be mindful of the tools and processes you use and refine them constantly.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why&#34;&gt;Why?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The single biggest question you should now be asking yourself is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Why do I want to become an Engineering Manager?&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This is really important, and requires you to be very honest and open with &lt;em&gt;yourself&lt;/em&gt; (not only will you suffer the consequences of a bad decision, but so will everyone else who is relying on you).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you answered the question with any one of the following (or more), then you need to seriously consider an alternative future career path; simply because you truly won&amp;rsquo;t be happy in this role otherwise:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I want more money&lt;/li&gt;&#xA;&lt;li&gt;I want a promotion&lt;/li&gt;&#xA;&lt;li&gt;I want a better job title&lt;/li&gt;&#xA;&lt;li&gt;I&amp;rsquo;m bored of writing code&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;To me, a &lt;em&gt;good&lt;/em&gt; reason to want to progress towards being an Engineering Manager is when you deep down know that your enjoyment comes from helping people and having a positive impact in &lt;em&gt;their&lt;/em&gt; ability to do great work and helping them to progress in their career.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If that is your motivation, then you have the right mentality for this type of role. If that&amp;rsquo;s not your intent, then that&amp;rsquo;s OK (don&amp;rsquo;t worry) but you will need to consider alternative options and really figure out what it is about working in tech/engineering that you enjoy, and do what you can to move more in that specific direction.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately if you want things like more money or a promotion or a better job title, that will require you to have more &lt;em&gt;impact&lt;/em&gt; at work, and to do &lt;em&gt;that&lt;/em&gt; means you need to lift your head up from your laptop and engage more widely with the organisation and the teams within and start demonstrating more broadly the potential positive impact that you can have.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see also my post on &amp;lsquo;&lt;a href=&#34;/posts/interview-techniques/&#34;&gt;Architecture Interviews (and other thoughts)&lt;/a&gt;&amp;rsquo;, where I cover what I look for when interviewing an Engineering Manager candidate.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;incremental-steps&#34;&gt;Incremental Steps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You might not be quite ready for a straight jump up to Engineering Manager, so what can you do in the meantime to help you move towards that goal? Here are some ideas&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Mentoring&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Most companies have a mentoring program, and even if not it doesn&amp;rsquo;t prevent you from reaching out to colleagues and offering them your help, guidance and the benefits of your experience (if they choose to accept it)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Take Responsibility&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Get involved with cross-team discussions&lt;/li&gt;&#xA;&lt;li&gt;Create a working-group for a topic you care about&lt;/li&gt;&#xA;&lt;li&gt;Support your team and reach out on their behalf if you&amp;rsquo;re able to&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Lead&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Take the responsibility of leading a project&lt;/li&gt;&#xA;&lt;li&gt;Beyond that take the opportunity to lead a team&lt;/li&gt;&#xA;&lt;li&gt;Help non-technical stakeholders understand the team&amp;rsquo;s work&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;manager-cheat-sheet&#34;&gt;Manager Cheat Sheet&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.buzzfeed.com/&#34; target=&#34;_blank&#34;&gt;BuzzFeed&lt;/a&gt; recently hired a new Engineering Manager 🎉 🙂&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Her name is &lt;a href=&#34;https://twitter.com/SBozhko&#34; target=&#34;_blank&#34;&gt;Svetlana Bozhko&lt;/a&gt; and she kindly shared with me a &amp;lsquo;cheat sheet&amp;rsquo; (of sorts) that helps her stay on-track/focused.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I know of other Engineering Managers/Directors of Engineering (some of whom work for a few of &amp;lsquo;the big 4&amp;rsquo;) who use a similar approach, and it&amp;rsquo;s something I personally like.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s an example of what such a &amp;lsquo;cheat sheet&amp;rsquo; might look like:&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;daily&#34;&gt;Daily&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Personal&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Am I ready for today&amp;rsquo;s meetings?&lt;/li&gt;&#xA;&lt;li&gt;Can I reduce the length of those meetings?&lt;/li&gt;&#xA;&lt;li&gt;Can I cancel any of those meetings?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;People&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Recruiting, Hiring, Interviewing&lt;/li&gt;&#xA;&lt;li&gt;Candidate follow-ups&lt;/li&gt;&#xA;&lt;li&gt;Sell the company, its vision, roles etc&lt;/li&gt;&#xA;&lt;li&gt;Close great candidates&lt;/li&gt;&#xA;&lt;li&gt;Observe team health&lt;/li&gt;&#xA;&lt;li&gt;Casual feedback sessions&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Processes&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Daily standups&lt;/li&gt;&#xA;&lt;li&gt;Am I ready for these standups?&lt;/li&gt;&#xA;&lt;li&gt;Any important company-wide updates?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Projects&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Are we on track with critical projects?&lt;/li&gt;&#xA;&lt;li&gt;Any docs/guides needed to be written?&lt;/li&gt;&#xA;&lt;li&gt;Any PRs waiting my approval/feedback?&lt;/li&gt;&#xA;&lt;li&gt;Should I step in on any engineering tasks?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;weekly&#34;&gt;Weekly&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Personal&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Have I setup my goals for this/next week?&lt;/li&gt;&#xA;&lt;li&gt;How do I progress with my goals?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;People&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1:1&amp;rsquo;s and enhancing their strengths&lt;/li&gt;&#xA;&lt;li&gt;Who needs additional feedback?&lt;/li&gt;&#xA;&lt;li&gt;Any tasks I can delegate?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Processes&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Review all tasks in backlog&lt;/li&gt;&#xA;&lt;li&gt;Any design/architecture discussions?&lt;/li&gt;&#xA;&lt;li&gt;Divide tasks into smaller ones&lt;/li&gt;&#xA;&lt;li&gt;Plan team retrospectives&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Projects&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Give status reports to my managers&lt;/li&gt;&#xA;&lt;li&gt;Who else do I need to update?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;monthly&#34;&gt;Monthly&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Personal&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What do I need to do to be more successful in my role?&lt;/li&gt;&#xA;&lt;li&gt;Any training I can do, mentoring I can give, books I can read?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;People&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ensure team vision is aligned&lt;/li&gt;&#xA;&lt;li&gt;Ensure team expectations are understood&lt;/li&gt;&#xA;&lt;li&gt;Any team events we should consider?&lt;/li&gt;&#xA;&lt;li&gt;1:1&amp;rsquo;s focused specifically on career growth&lt;/li&gt;&#xA;&lt;li&gt;Anyone moved into new roles?&lt;/li&gt;&#xA;&lt;li&gt;Do I need to set new expectations?&lt;/li&gt;&#xA;&lt;li&gt;Any changes to the career ladder?&lt;/li&gt;&#xA;&lt;li&gt;What changes would make it more fun to work here?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Processes&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Challenge and question existing processes&lt;/li&gt;&#xA;&lt;li&gt;Are the current sprint metrics still useful?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Projects&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Any strategic ideas to improve current projects?&lt;/li&gt;&#xA;&lt;li&gt;Do we need a new project?&lt;/li&gt;&#xA;&lt;li&gt;Dow we need to stop a project?&lt;/li&gt;&#xA;&lt;li&gt;Any strategic hires needed?&lt;/li&gt;&#xA;&lt;li&gt;Budget and capacity planning&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So what do &lt;em&gt;you&lt;/em&gt; think? Is there anything here that you disagree with, or something you feel I missed altogether? Let me know on twitter!&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/engineer-to-manager/</guid>
      <link>https://www.integralist.co.uk/posts/engineer-to-manager/</link>
      <pubDate>Sat, 25 Aug 2018 00:00:00 +0000</pubDate>
      <title>Engineer to Manager</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post will explain a little bit about a particular type of interview: an architecture interview. It&amp;rsquo;ll breakdown what it is, why using whiteboards isn&amp;rsquo;t necessarily a bad thing to use in an interview context, as well as understanding a bit about what it is we&amp;rsquo;re looking for from a particular candidate (in this post the information will be related to interviewing someone for an Engineering Manager opportunity).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-an-architecture-interview&#34;&gt;What is an architecture interview?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An architecture review can be a few different things depending on the context of the interview and the type of role being applied for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically, for a software engineering role, a candidate will be asked to design a system architecture based on the interviewer&amp;rsquo;s given requirements.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is typically carried out on a whiteboard, but pen and paper is sufficent too (although harder for both candidate and interviewer to share and discuss over).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Whereas for a more senior role, like an engineering manager (or even a director of engineering), the format will change to one where the candidate is asked to &lt;em&gt;present&lt;/em&gt; a system architecture they&amp;rsquo;ve been involved with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for the switch around of formats is that generally the more senior roles won&amp;rsquo;t necesarily be controlling the system design (they&amp;rsquo;ll have input, but generally speaking this would be the responsibility of individual teams), and so what you&amp;rsquo;re trying to gauge from that type of interview is an understanding of whether they have a solid technical grounding, because their other skills are of a bigger priority.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;is-one-interview-all-it-takes&#34;&gt;Is one interview all it takes?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;No. To clarify: when interviewing a candidate, you won&amp;rsquo;t give them a single architecture interview and call it a day (i.e. make a decision). There are many interviews that need to happen before you can make such a decision:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Architecture&lt;/li&gt;&#xA;&lt;li&gt;Organizational&lt;/li&gt;&#xA;&lt;li&gt;Team Values&lt;/li&gt;&#xA;&lt;li&gt;Executive&lt;/li&gt;&#xA;&lt;li&gt;Cross-Discipline&lt;/li&gt;&#xA;&lt;li&gt;Team Managment&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the above are based on a &amp;lsquo;Director of Engineering&amp;rsquo; day of interviews, but you&amp;rsquo;d have similar formats for varying engineering roles.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;aren-t-whiteboard-interviews-bad&#34;&gt;Aren&amp;rsquo;t whiteboard interviews bad?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In summary: no (at least they&amp;rsquo;re not inherently bad).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you say &amp;ldquo;whiteboard interview&amp;rdquo;, people generally tend to cringe and think of past experiences of being told to solve X problem using Y algorithm, and writing out chunks of pseudo-code with pen and paper.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But let&amp;rsquo;s be honest, that rarely correlates to the &lt;em&gt;actual&lt;/em&gt; work you typically end up doing, and so to describe that format as &amp;ldquo;wrong&amp;rdquo; would be correct †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† although, as with everything, it can depend on the role you&amp;rsquo;re hiring for of course.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;For me, that type of whiteboarding session is a problem. Whiteboard interviews of &lt;em&gt;that&lt;/em&gt; nature, the ones that have you jumping through hoops to perform some kind of mathematical trickery are at best useless, and at worst very stressful. They&amp;rsquo;re also likely to result in a candidate leaving unenthused and saying bad things about the company and its interview process on social media.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should not be having whiteboard interviews consisting of questions of that kind. Whereas architecture interviews are (in my experience any way) about more about discussing &amp;lsquo;high-level&amp;rsquo; concepts, and demonstrating &amp;lsquo;practical&amp;rsquo; problem solving skills which are applicable at many different levels of experience, and useful in many different situations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If structured (and presented) correctly by the interviewer, a whiteboard interview (such as an architecture interview) can actually be fun for both the candidate and the interviewer, and be an enlightening experience rather than a stressful one.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-should-an-architecture-interview-be-handled&#34;&gt;How should an architecture interview be handled?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The goal (for &lt;em&gt;any&lt;/em&gt; interview) is to allow the candidate to shine, and to present themselves in the best light that they can. Even if you decide they&amp;rsquo;re not right for the role or the organisation, you want them to walk away feeling good about themselves and what they did that day.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To hopefully achieve that goal, we want the candidate to feel relaxed and that they have everything they need &lt;em&gt;before&lt;/em&gt; the interview begins (do they need a toilet break? do they need a glass of water? make sure you ask and that they&amp;rsquo;re comfortable).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, tell them the agenda. Just as an example it might go something like:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;ldquo;We have 90mins and then you move to your next interview. So I reckon we should spend five minutes introducing ourselves and what we do here (the teams we work in etc), and then the next hour chatting about the problem to be solved (or the architecture you&amp;rsquo;re going to present), and then after that it&amp;rsquo;s up to you: we could either use up the rest of the time by having you ask &lt;em&gt;us&lt;/em&gt; questions &amp;ndash; anything you like, or we could do that for 15 minutes and the remaining time you can have back to relax and we can show you around the office a bit&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Doesn&amp;rsquo;t have to be exactly like that, but basically you want the candidate to know what&amp;rsquo;s going on (no surprises or ambiguity). So, you might also want to make sure the candidate is ok with you taking notes (my memory is terrible and so much happens during an interview that you want to be able to go back over your notes to be sure you&amp;rsquo;ve taken everything into consideration).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As far as the actual &amp;lsquo;test&amp;rsquo; portion of the architecture interview, remember that people solve problems in different ways to you so be open-minded when critiquing their design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, and most importantly, when dealing with a software engineer (i.e. you&amp;rsquo;re giving them requirements to fulfill as part of the design), make sure you&amp;rsquo;re working &lt;em&gt;with&lt;/em&gt; that person. Help guide them when it looks like they might be losing their way, you don&amp;rsquo;t have to outright tell them the answer, but you can ask leading questions that should otherwise help kickstart their thinking down a better path. You&amp;rsquo;d do this for any colleague you work with, so afford this person the same respect and kindness.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-are-you-looking-for-from-a-candidate&#34;&gt;What are you looking for from a candidate?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, for me, it depends on the role. I&amp;rsquo;ve carried out quite a few &amp;lsquo;Engineering Manager&amp;rsquo; interviews recently and so they&amp;rsquo;re the most prominent in my mind so I&amp;rsquo;ll use that as my measuring stick (but just remember, none of this is set in stone and is open for interpretation and tweaking/evolving).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So below are the high-level perspectives I&amp;rsquo;m looking for, and taking notes on. But realise you won&amp;rsquo;t be able to incorporate all of these into your single architecture interview. It wouldn&amp;rsquo;t be practical, nor would it make sense to do that (especially if you have multiple interview formats for this candidate). These topics are more generally applicable.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Communication&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;are they &amp;lsquo;remote aware&amp;rsquo;? I&amp;rsquo;m generally interviewing remotely, so when there are other interviewers in the room (in real life), it&amp;rsquo;s often the case I&amp;rsquo;m not interacted with in the same way as others.&lt;/li&gt;&#xA;&lt;li&gt;do they use gender appropriate language?&lt;/li&gt;&#xA;&lt;li&gt;do they communicate clearly and circle back to questions they forgot to answer?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;System&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;are they able to describe the history of the project, its reason for existing, the value it&amp;rsquo;s supposed to offer, the teams and other comms involved?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Architecture&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;is it a good design? fundamental but just be aware that in most cases this becomes a subjective opinion, and so unless there are some horrific consequences to the design, then it&amp;rsquo;s &lt;a href=&#34;https://twitter.com/aprilwensel/status/1030322280042180610&#34; target=&#34;_blank&#34;&gt;not actually something to worry too deeply about&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Risk Management&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is the system fault tolerant? What scenarios were considered?&lt;/li&gt;&#xA;&lt;li&gt;Were risks identified (if so what were they)?&lt;/li&gt;&#xA;&lt;li&gt;How were those risks managed/mitigated?&lt;/li&gt;&#xA;&lt;li&gt;Was the risk monitored?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What telemetry system was used to gather data?&lt;/li&gt;&#xA;&lt;li&gt;What types of instrumentation is in places (logging, metrics, both or other)?&lt;/li&gt;&#xA;&lt;li&gt;What monitoring tools are in place?&lt;/li&gt;&#xA;&lt;li&gt;See also this post about &lt;a href=&#34;/posts/monitoring-best-practices/&#34;&gt;monitoring best practices&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;How is on-call handled (is there a culture of responsibility or is there a centralized operations team looking after things)?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Strategy&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What teams were consulted/impacted?&lt;/li&gt;&#xA;&lt;li&gt;Who were the stake holders, and what were their involvement?&lt;/li&gt;&#xA;&lt;li&gt;How was the system proposed and communicated?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Distribution&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is the candidate used to working within a large multi-region organisation where teams are distributed across many different time zones (are they used to those types of challenges)?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Organisation&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What is the structure and hierarchy of their current employer? Is it fairly flat or lots of layers and red tape? Maybe it&amp;rsquo;s &amp;ldquo;goldilocks&amp;rdquo; (i.e. &lt;em&gt;just right&lt;/em&gt;)?&lt;/li&gt;&#xA;&lt;li&gt;Has there been any restructuring of the teams (why), and how was it communicated, how was the changes received by staff?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Awareness&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Was the candidate actively thinking about things outside of just the technical aspect? Were they thinking about, for example, the costs associated with the architecture they were designing and how to reduce those costs whilst trying to still solve the problem at hand?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Team Management&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How does the candidate handle 1:1 meetings, build relationships and give feedback?&lt;/li&gt;&#xA;&lt;li&gt;How big is the team(s) they manage, what conflicts have they needed to resolve, and how?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Organisation Feedback/Inclusion&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Does their current employer provide staff the means to give &lt;em&gt;them&lt;/em&gt; feedback and to understand the health of their organisation?&lt;/li&gt;&#xA;&lt;li&gt;If so what are those tools and what has their effectiveness and impact been?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Diversity&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is the candidate thinking about diversity and how to improve it in the hiring process?&lt;/li&gt;&#xA;&lt;li&gt;What tools do they use to help with that goal?&lt;/li&gt;&#xA;&lt;li&gt;Are there any community programs they support or host?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Interest&lt;/strong&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is the candidate excited to work for/with us? What about our organisation do they like the most? (this isn&amp;rsquo;t a deal breaker, this is more out of interest)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;anything-else&#34;&gt;Anything else?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t know, but maybe you could let me know on twitter if there&amp;rsquo;s anything I&amp;rsquo;ve missed or should be doing differently. Feedback appreciated.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/interview-techniques/</guid>
      <link>https://www.integralist.co.uk/posts/interview-techniques/</link>
      <pubDate>Sat, 18 Aug 2018 00:00:00 +0000</pubDate>
      <title>Interview Techniques</title>
    </item>
    <item>
      <description>&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for those short on time: here&amp;rsquo;s the &lt;a href=&#34;https://docs.google.com/document/d/1rYERE1LaobML3puIa94jJSh2cQ0kHflCk8zmVo3pWq0/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;Post-Mortem Template&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-post-mortem&#34;&gt;What is a post-mortem?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you have a service outage, or any form of unexpected service disruption, you first resolve the issue and then proceed to discuss what happened, why and how.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The process of discussion is referred to as a &amp;lsquo;post-mortem&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-do-we-make-post-mortems-effective&#34;&gt;How do we make post-mortems effective?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You shouldn&amp;rsquo;t just get a bunch of people together in a room to discuss an incident. You need to:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Schedule the meeting at the right time.&lt;/li&gt;&#xA;&lt;li&gt;Invite the right people.&lt;/li&gt;&#xA;&lt;li&gt;Have the right attitude.&lt;/li&gt;&#xA;&lt;li&gt;Talk about the right things.&lt;/li&gt;&#xA;&lt;li&gt;Know the right follow-up actions to take.&lt;/li&gt;&#xA;&lt;li&gt;Notify the right people.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s go over each of these items briefly, they might &lt;em&gt;sound&lt;/em&gt; obvious but I&amp;rsquo;ve seen each of them carried out in vastly different ways (hint: not all of them good)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;schedule-the-meeting-at-the-right-time&#34;&gt;Schedule the meeting at the right time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You should schedule the post-mortem to occur &lt;em&gt;as soon as possible&lt;/em&gt; after the event. DO NOT have this discussion two weeks after the incident because people will forget important details. Have this discussion while everything is still fresh in people&amp;rsquo;s minds.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The trouble with getting a post-mortem scheduled at the right time is that you&amp;rsquo;ll need a prepared document (a post-mortem template) that is filled in with as much detail (as can be reasonably recalled from memory †) almost immediately after the incident. This document doesn&amp;rsquo;t just magically appear, it&amp;rsquo;s someones responsibility to create it.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this is harder than you imagine, even with modern day communication tools like &lt;a href=&#34;https://slack.com/&#34; target=&#34;_blank&#34;&gt;Slack&lt;/a&gt;, there are so many things going on at once (multiple people chatting and trying to isolate the problem, then finding a quick and safe solution) that it&amp;rsquo;s easy to forget things or not notice them happening (hence a post-mortem helps bring all this information together).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You should have the post-mortem document filled in (as much as you can) &lt;em&gt;before&lt;/em&gt; having the post-mortem as a way to help drive the conversation, and (ideally) whoever was on-call at the time of the incident would be marked as the point-person for prepping this post-mortem document.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One last useful point is to make sure all those who need to be involved in the post-mortem are reminded of the meeting a day before. This allows them to read through the post-mortem document and prep accordingly (and generally makes for a smoother discussion).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;invite-the-right-people&#34;&gt;Invite the right people&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is a tricky one to get right, and will vary depending on your organisational structure (and even how the incident itself unfolded).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You shouldn&amp;rsquo;t invite only those people involved during the incident because there are insights that can be gained from Product Managers (just as an example) who might not have been online at the time of the incident, and who might be able to elucidate certain aspects that the engineers/support team were not aware of.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You also don&amp;rsquo;t necessarily want to invite too many people outside of those involved in the incident. As the old saying goes: &amp;ldquo;too many cooks spoil the broth&amp;rdquo;. You could find the &amp;lsquo;noise to signal&amp;rsquo; ratio goes up.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;have-the-right-attitude&#34;&gt;Have the right attitude&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Post-mortems should be &lt;em&gt;blameless&lt;/em&gt;. Do not come into the meeting with an &amp;lsquo;axe to grind&amp;rsquo;. People make mistakes, we&amp;rsquo;re dealing with software and often-times complex distributed systems so we should have an attitude of support, understanding, patience and a willingness to want to genuinely improve things.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;talk-about-the-right-things&#34;&gt;Talk about the right things&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is where the post-mortem &amp;lsquo;template&amp;rsquo; comes in (I&amp;rsquo;ve linked to it at the top and bottom of this post), as it includes different topics that can help steer the conversation in the right direction.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Things like: observations, symptoms, hypothesis, remediation, impact etc. You should also identify who the meeting moderator is (the person responsible for keeping the meeting on track and not falling into a war of words) and also who the notetaker is (they can&amp;rsquo;t be the same person).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also probably worth mentioning that you shouldn&amp;rsquo;t be having a 3 hour meeting (of any kind, let alone a post-mortem), so make sure the short time you have together is yielding the right feedback and information.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;know-the-right-follow-up-actions-to-take&#34;&gt;Know the right follow-up actions to take&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Have real &lt;em&gt;actionable&lt;/em&gt; tasks as takeways from the post-mortem. You don&amp;rsquo;t want to just discuss how things &lt;em&gt;could&lt;/em&gt; be improved, you want to &lt;em&gt;actually&lt;/em&gt; improve them. It&amp;rsquo;s very important you take this opportunity to identity things you &lt;em&gt;can&lt;/em&gt; do to prevent this issue from occuring again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If service downtime/disruption is important to your business (and let&amp;rsquo;s face it, when is it not), then you need to take incidents seriously and put the time and effort into ensuring stability for the future.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have the post-mortem document filled in fully, reviewed and all takeway tasks have been actioned (or at least scheduled to be actioned in the near future), then you can finish up this whole process by sharing what you learnt with your colleagues who were not involved (which leads us onto the next point).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;notify-the-right-people&#34;&gt;Notify the right people&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We generally take the finished post-mortem document and email it around to our development mailing list so that all engineers in the organsation get to see what happened, why, and how it was resolved.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is super important because there are so many benefits that can come from this sharing of knowledge. Probably top of that list would be that it supports the notion that your organisation respects &amp;lsquo;accountability&amp;rsquo; and that it&amp;rsquo;s honest about mistakes that are made.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It highlights to others (not just tech and engineering) that these mistakes aren&amp;rsquo;t punished but treated as &lt;em&gt;opportunities&lt;/em&gt; for growth and learning. As well as exposing engineers (of varying skill levels) to different architectures, systems and services that are in place and helps them not only understand them a little better but encourages them to investigate more.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because of all that (and more), who you share the post-mortem document with really does depend on you and your company&amp;rsquo;s values/standards.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;a-template-for-success&#34;&gt;A template for success&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below I link to a Google document we use as a template for our post mortem meetings, and I&amp;rsquo;ve included the relevant sections below just for an &amp;lsquo;at a glance&amp;rsquo; view.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you don&amp;rsquo;t have to include all of these if you don&amp;rsquo;t want. Take what is useful to you and leave whatever isn&amp;rsquo;t.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;observations&#34;&gt;Observations&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What empircal things did people see?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. System X was Y, which indicated Z.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;symptoms&#34;&gt;Symptoms&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What was the physical outcome (the user experience) of these observations?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. Users were seeing X output.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;hypothesis&#34;&gt;Hypothesis&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What do we believe to be the contributing factors?&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there&amp;rsquo;s typically never a single &amp;lsquo;root cause&amp;rsquo;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;remediation&#34;&gt;Remediation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What did we do to resolve the incident?&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this isn&amp;rsquo;t the same as &amp;lsquo;fixing&amp;rsquo; the problem, which suggests something more long term was put in place.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We did X to resolve the problem.&lt;/li&gt;&#xA;&lt;li&gt;We also did Y to resolve the problem.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;impact&#34;&gt;Impact&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What was the &amp;lsquo;cost&amp;rsquo; of this incident?&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this isn&amp;rsquo;t the same thing as the symptoms.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Thing A broke for N hours.&lt;/li&gt;&#xA;&lt;li&gt;Thing B broke and all entered data for User C, during the incident, was lost.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;key-points&#34;&gt;Key Points&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s lots of interactions during the incident, what were the most important things that happened?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Person A identified incident at N time.&lt;/li&gt;&#xA;&lt;li&gt;Person B notified stakeholders at N time.&lt;/li&gt;&#xA;&lt;li&gt;Person C ramped up resources at N time.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;participants&#34;&gt;Participants&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Who was involved and what are their roles in the company.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you don&amp;rsquo;t know everyone and what they do, so make it easier for people reading the post-mortem to understand the breadth of skills involved.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Jane Doe (Engineer)&lt;/li&gt;&#xA;&lt;li&gt;Joe Bloggs (Support Staff)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;timeline&#34;&gt;Timeline&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Describe what happened and when. This should be much more detail than those extracted for the &amp;lsquo;key points&amp;rsquo; section.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you work for a distributed company, then identifying the timezone of the incident (or at least the timezone you&amp;rsquo;re reporting it from) can help clarify when these things happened.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Timezone: BST&#xA;2018-12-22 (Saturday)&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;03:00 - Joan said a thing happened.&lt;/li&gt;&#xA;&lt;li&gt;03:10 – Joe notified the stakeholders.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;additional-details&#34;&gt;Additional Details&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Not everything said is going to have happened within the incident channel you were looking at during the incident (maybe it happened in an email thread between support staff, product and other stakeholders). This is something that is likely to be fleshed out during the post-mortem itself as more people who were having those conversations give their perspective.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Bilbo Baggins (Product Manager): said something useful that not everyone would have seen&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;communication&#34;&gt;Communication&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Where was the &amp;lsquo;war room&amp;rsquo; (i.e. the incident channel where everyone was gathered to help problem solve)?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;#some-slack-channel&lt;/li&gt;&#xA;&lt;li&gt;Link to Logs&lt;/li&gt;&#xA;&lt;li&gt;Link to Dashboards&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;images&#34;&gt;Images&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you have any screen shots of the broken system, then that&amp;rsquo;s useful for people not involved to understand the impact more visually. But also, linking to a specific point in time of a graph that shows a spike (and hopefully dip later) in errors can also be useful to reference back to.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;tasks&#34;&gt;Tasks&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Put together a list of tasks for people to complete. Doesn&amp;rsquo;t have to be done at the time of sending out the post-mortem document to the wider organisation, but &lt;em&gt;ideally&lt;/em&gt; you&amp;rsquo;d have those things done before you sent it out.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Jane: responsible for doing this task.&lt;/li&gt;&#xA;&lt;li&gt;Another task that has no specific person assigned to it.&lt;/li&gt;&#xA;&lt;li&gt;Confirm to Bilbo that we’ve done everything we can.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;questions&#34;&gt;Questions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;During the post-mortem questions will be raised and they should be placed here. You&amp;rsquo;re not necessarily going to have all the answers during that meeting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ideally you&amp;rsquo;d have answers tied to this questions before you sent out the post-mortem document to the wider organisation though.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;what-we-did-well&#34;&gt;What we did well&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A list of things the team did well during the incident.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The incident was identified quickly&lt;/li&gt;&#xA;&lt;li&gt;The solution was quickly rolled out&lt;/li&gt;&#xA;&lt;li&gt;No one panicked&lt;/li&gt;&#xA;&lt;li&gt;Cross team communication was exceptional&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;what-we-didn-t-do-so-well&#34;&gt;What we didn’t do so well&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A list of things the team didn&amp;rsquo;t do so well during the incident.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It took a long time to understand what the alarm meant and who was affected&lt;/li&gt;&#xA;&lt;li&gt;The on-call person didn&amp;rsquo;t acknowledge the initial alarm and so it kept firing&lt;/li&gt;&#xA;&lt;li&gt;We didn&amp;rsquo;t setup an incident slack channel so conversations were happening everywhere&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;what-can-we-learn-from-in-future&#34;&gt;What can we learn from in future?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A list of the things we should pro-actively improve upon. Generally this will be resolutions to the things that didn&amp;rsquo;t go well.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;template-document&#34;&gt;Template Document&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;View the &lt;a href=&#34;https://docs.google.com/document/d/1rYERE1LaobML3puIa94jJSh2cQ0kHflCk8zmVo3pWq0/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;Post-Mortem Template&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let me know what you think on twitter. If you have any improvements or you think I have things totally wrong, then I&amp;rsquo;d love to hear about it.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/post-mortems/</guid>
      <link>https://www.integralist.co.uk/posts/post-mortems/</link>
      <pubDate>Thu, 09 Aug 2018 00:00:00 +0000</pubDate>
      <title>Post Mortems</title>
    </item>
    <item>
      <description>&lt;p&gt;So this post is a long time coming. It has been pushed to the forefront by the fact that BuzzFeed recently held its annual &amp;lsquo;Hack Week&amp;rsquo;, and riding on the wind of a massive success I&amp;rsquo;ve had with my hack project this past week&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Mark has casually saved the company $60k a year by letting us break away from a commercial dependency without losing any features!&amp;rdquo; &amp;ndash; BuzzFeed UK Newsletter&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;I&amp;rsquo;ve decided to revisit &lt;em&gt;last years&lt;/em&gt; hack week project: &lt;strong&gt;OpsBot&lt;/strong&gt;, which is a Slackbot for operational tasks.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for those interested, the presentation slides for my 2018 hack can be found &lt;a href=&#34;../../pdfs/hackweek_2018_nginx.pdf&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;what-does-opsbot-do&#34;&gt;What does OpsBot do?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Creates standardized incident channels.&lt;/li&gt;&#xA;&lt;li&gt;Auto-invite users to incident channel based on emoji reactions.&lt;/li&gt;&#xA;&lt;li&gt;Looks up service runbooks.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;how-do-you-use-opsbot&#34;&gt;How do you use OpsBot?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;/incident &amp;lt;name&amp;gt; [visibility] [reporter]&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/runbook &amp;lt;service&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s break down the arguments provided to each command:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;name&lt;/code&gt; (required):&lt;br&gt;&#xA;hyphenated name of the incident, e.g. &lt;code&gt;Service-Foo-5xx&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;visibility&lt;/code&gt; (optional):&lt;br&gt;&#xA;whether the channel should be public or private&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;reporter&lt;/code&gt; (optional; has a default channel):&lt;br&gt;&#xA;name of channel where incident was first reported&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;service&lt;/code&gt; (required):&lt;br&gt;&#xA;searches our company Google Drive for specified runbook&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;incident-example&#34;&gt;Incident Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine I&amp;rsquo;ve noticed something bad has happened. I&amp;rsquo;ll go to the appropriate Slack channel and report it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At that point people who are interested in the incident will use an 👀 emoji (we support various types) to indicate their interest in being auto-invited to a new incident channel (if one is to be created).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following image demonstrates what that might look like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/opsbot_1.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/opsbot_1.png&#34; alt=&#34;opsbot 1&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we have automated notifications sent to specific monitoring slack channels, and so people can also use the emoji reaction on those messages.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now imagine this incident has been triaged and yes it is indeed a problem. We&amp;rsquo;ll need to spin up an incident channel so we can focus discussions and get a resolution in place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s at that point someone runs the command: &lt;code&gt;/incident bf4life&lt;/code&gt; (or whatever you want to name the incident 😉) and we&amp;rsquo;ll see the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/opsbot_2.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/opsbot_2.png&#34; alt=&#34;opsbot 2&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice that we automatically prefix the given incident name with the current date, so it&amp;rsquo;s easier to go back and review/identify past incidents.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we&amp;rsquo;re dealing with a service that we&amp;rsquo;re unfamiliar with, then we might also want to look at the runbook(†) for that service.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† a runbook is a compilation of routine procedures and operations that the system administrator or operator carries out &amp;ndash; Wikipedia&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This is when someone runs the command: &lt;code&gt;/runbook site router&lt;/code&gt; (or whatever the affected service is) and we&amp;rsquo;ll see the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/opsbot_3.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/opsbot_3.png&#34; alt=&#34;opsbot 3&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-does-opsbot-work&#34;&gt;How does OpsBot work?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When creating an incident channel, OpsBot will link back to the channel that reported the incident as well as linking to the specific notification in that channel.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This works because OpsBot&amp;rsquo;s logic is trying to match one of two possible patterns within the message&amp;rsquo;s body:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The phrase &lt;code&gt;ISSUE:&lt;/code&gt; begins the message (see example from earlier ☝️).&lt;/li&gt;&#xA;&lt;li&gt;The message is identified as a automated NAGIOS &lt;code&gt;CRITICAL&lt;/code&gt; notification.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;If the message is identified as an &amp;lsquo;incident trigger&amp;rsquo; then that&amp;rsquo;s what we link to within the incident channel&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/opsbot_4.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/opsbot_4.png&#34; alt=&#34;opsbot 4&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-did-we-learn&#34;&gt;What did we learn?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Have a pre-hack document with feature specifications in place.&lt;/li&gt;&#xA;&lt;li&gt;Slackbots are fun to create.&lt;/li&gt;&#xA;&lt;li&gt;The Google API was &lt;del&gt;kinda tricky&lt;/del&gt; a PITA.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;what-could-we-improve&#34;&gt;What could we improve?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Two issues cropped up fairly early on in the design:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Identify who &lt;em&gt;not&lt;/em&gt; to auto-invite to a private incident.&lt;/li&gt;&#xA;&lt;li&gt;Identify better &amp;lsquo;nagios incident message&amp;rsquo; grouping logic.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The first issue is an awkward one because we can&amp;rsquo;t necessarily stop people from accessing a private incident channel if they&amp;rsquo;ve gone into a public slack channel and used the emoji reaction on a particular incident.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That being said, we very rarely have to create private incident channels. That&amp;rsquo;s only when an incident relates to some serious security vulnerability, and nearly all the time those types of issues are raised via HackerOne and dealt with outside of typical monitoring notifications (like 5xx&amp;rsquo;s).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second incident occurs when people add an emoji to a NAGIOS automated notification but then a repeat notification message is sent later. In this scenario a message pings to say there is an issue, people add the emoji reaction but later on (before an incident channel has been created) an updated NAGIOS error notification is sent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when we create the incident channel, it&amp;rsquo;ll look for the &lt;em&gt;first&lt;/em&gt; NAGIOS warning that matches and it&amp;rsquo;ll find no emoji reactions, so it won&amp;rsquo;t auto-invite people to the incident channel.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although this isn&amp;rsquo;t the end of the world as people can still see the incident channel link generated (if it&amp;rsquo;s a public channel) and click on that to access the incident channel.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-else-could-opsbot-do&#34;&gt;What else &lt;em&gt;could&lt;/em&gt; OpsBot do?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OpsBot has the potential to do lots of things, it just depends on your needs and use cases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For us, a few things we planned to do but never quite got round to was&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;code&gt;/postmortem&lt;/code&gt; command for automatically creating our incident &amp;lsquo;Post Mortem&amp;rsquo; documents.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;code&gt;/service&lt;/code&gt; command for looking up the on-call team leads for that service(†).&lt;/li&gt;&#xA;&lt;li&gt;Add runbook info to our deployment platform so OpsBot can pull it in auto-magically.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;em&gt;damn good refactor&lt;/em&gt; and some tests! (this was a &amp;lsquo;hack&amp;rsquo; after all).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this might materialise into another project we have for improving team relations called &lt;code&gt;#WhoWhatWhy&lt;/code&gt; (coming soon).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So that&amp;rsquo;s OpsBot. If you&amp;rsquo;re interested, the presentation slides for the OpsBot hack can be found &lt;a href=&#34;../../pdfs/hackweek_2017_opsbot.pdf&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/slackbot-opsbot/</guid>
      <link>https://www.integralist.co.uk/posts/slackbot-opsbot/</link>
      <pubDate>Tue, 07 Aug 2018 00:00:00 +0000</pubDate>
      <title>OpsBot: Operations Slackbot</title>
    </item>
    <item>
      <description>&lt;p&gt;This post is going to explain the importance of interfaces, and the concept of programming to abstractions (using the &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; programming language), by way of a simple example.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;While treading what might seem like familiar ground to some readers, this is a fundamental skill to understand because it enables you to design more flexible and maintable services.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;interfaces-in-go&#34;&gt;Interfaces in Go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An &amp;lsquo;interface&amp;rsquo; is a contract which describes &lt;em&gt;behaviour&lt;/em&gt; (not &lt;em&gt;data&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://medium.com/@andreiboar/7-common-interface-mistakes-in-go-1d3f8e58be60&#34; target=&#34;_blank&#34;&gt;Andrei Boar&lt;/a&gt; said&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;When defining interfaces in Go, you don’t define what something &lt;em&gt;is&lt;/em&gt; but what it &lt;em&gt;provides&lt;/em&gt; — behavior, not things! That’s why there’s no File interface in Go, but a Reader and a Writer: these are behaviors, and File is a thing implementing Reader and Writer.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;which is important because this has a direct effect on the naming of an&#xA;interface. You name interfaces with an &lt;em&gt;-er&lt;/em&gt; at the end to indicate it&amp;rsquo;s a verb&#xA;(i.e. this thing &lt;em&gt;does&lt;/em&gt; something).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Go an interface is defined like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Fooer interface {&#xA;    Bar(s string) (string, error)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;In Go, a capitalised name (method, field etc) is public, lowercase is private.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If an object in your code implements a &lt;code&gt;Bar&lt;/code&gt; function, with the exact same signature (e.g. accepts a string and returns either a string or an error), then that object is said to &lt;em&gt;implement&lt;/em&gt; the &lt;code&gt;Fooer&lt;/code&gt; interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An example of this would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type thing struct{}&#xA;&#xA;func (l *thing) Bar(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you can define a function that will accept that object, as long as it fulfils the &lt;code&gt;Fooer&lt;/code&gt; interface, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func doStuffWith(thing Foo)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is different to other languages, where you have to &lt;em&gt;explicitly&lt;/em&gt; assign an interface type to an object, like with Java:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;class testClass implements Foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Because of this flexibility in how interfaces are &amp;lsquo;applied&amp;rsquo;, it also means that an object could end up implementing &lt;em&gt;multiple&lt;/em&gt; interfaces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, imagine we have the following two interfaces:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Fooer interface {&#xA;  Bar(s string) (string, error)&#xA;}&#xA;&#xA;type Beeper interface {&#xA;  Beep(s string) (string, error)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can define an object that fulfils &lt;em&gt;both&lt;/em&gt; interfaces simply by implementing the functions they define:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type thing struct{}&#xA;&#xA;func (l *thing) Bar(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&#xA;func (l *thing) Beep(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;This is a bit of silly example, and so you&amp;rsquo;ll notice the method signature for each type is effectively the same. Be careful when designing your interfaces, because in this case we could possibly combine these two interfaces into a single (more generic) interface.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;name-your-interface-arguments&#34;&gt;Name Your Interface Arguments&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider the following interface:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Mover interface {&#xA;  Move(context.Context, string, string) error&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Do you know what the second and third arguments refer to and how the function will use them?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now consider this refactored version where the arguments have names associated with them:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Mover interface {&#xA;  Move(context.Context, source string, destination string) error&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now &lt;em&gt;that&lt;/em&gt; is better, because we can clearly see what the expectations are: the second argument is the &amp;lsquo;source&amp;rsquo; and the third argument is the &amp;lsquo;destination&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;keep-interfaces-small&#34;&gt;Keep Interfaces Small&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll find in the &lt;a href=&#34;https://go-proverbs.github.io/&#34; target=&#34;_blank&#34;&gt;Go Proverbs&lt;/a&gt;, the following useful tip:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The bigger the interface, the weaker the abstraction.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The reason for this is due to how interfaces are designed in Go and the fact that an object can potentially support multiple interfaces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By making an interface too big, we reduce an object&amp;rsquo;s ability to support it. Consider the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type FooBeeper interface {&#xA;  Bar(s string) (string, error)&#xA;  Beep(s string) (string, error)&#xA;}&#xA;&#xA;type thing struct{}&#xA;&#xA;func (l *thing) Bar(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&#xA;func (l *thing) Beep(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&#xA;type differentThing struct{}&#xA;&#xA;func (l *differentThing) Bar(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&#xA;type anotherThing struct{}&#xA;&#xA;func (l *anotherThing) Beep(s string) (string, error) {&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we&amp;rsquo;ve defined a &lt;code&gt;FooBeeper&lt;/code&gt; interface that requires two methods: &lt;code&gt;Bar&lt;/code&gt; and &lt;code&gt;Beep&lt;/code&gt;. Now if we look at the various objects we&amp;rsquo;ve defined &lt;code&gt;thing&lt;/code&gt;, &lt;code&gt;differentThing&lt;/code&gt; and &lt;code&gt;anotherThing&lt;/code&gt; we&amp;rsquo;ll find:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;thing&lt;/code&gt;: fulfils the &lt;code&gt;FooBeeper&lt;/code&gt; interface&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;differentThing&lt;/code&gt;: does &lt;em&gt;not&lt;/em&gt; fulfil the &lt;code&gt;FooBeeper&lt;/code&gt; interface&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;anotherThing&lt;/code&gt;: does &lt;em&gt;not&lt;/em&gt; fulfil the &lt;code&gt;FooBeeper&lt;/code&gt; interface&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Alternatively, if we were to break the &lt;code&gt;FooBeeper&lt;/code&gt; interface up into separate smaller interfaces (like we demonstrated earlier), then in our above example, the &lt;code&gt;differentThing&lt;/code&gt; and &lt;code&gt;anotherThing&lt;/code&gt; would become more re-usable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s ultimately what this Go proverb is suggesting: smaller interfaces allow for greater code reuse.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;accept-interfaces-return-concrete-types&#34;&gt;Accept Interfaces, Return Concrete Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If your function accepts a concrete type then you&amp;rsquo;ve limited the consumers ability to provide different implementations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider a function only accepting the concrete type &lt;code&gt;*os.File&lt;/code&gt; instead of the &lt;code&gt;io.Writer&lt;/code&gt; interface. Now try swapping out the &lt;code&gt;os.File&lt;/code&gt; implementation in a test environment, you&amp;rsquo;ll have a hard time vs mocking this using a struct that has the relevant interface methods.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unless there is a good reason to, you should return concrete types instead of interfaces. This is because an interface has a tendency to add an unnecessary layer of indirection for consumers of your package (although we&amp;rsquo;ll discover a few valid scenarios where returning an interface is more appropriate).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of what I mean by &lt;em&gt;indirection&lt;/em&gt;. We have a function &lt;code&gt;foo&lt;/code&gt; that returns the interface &lt;code&gt;Fooer&lt;/code&gt;, and yet we want to access a field on the underlying type of the interface (which we can see is a &lt;code&gt;S&lt;/code&gt; struct type):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;log&amp;quot;&#xA;)&#xA;&#xA;type Fooer interface {&#xA;    Bar()&#xA;}&#xA;&#xA;type S struct {&#xA;    Debug bool&#xA;}&#xA;&#xA;func (s S) Bar() {&#xA;    fmt.Println(&amp;quot;bar called&amp;quot;)&#xA;}&#xA;&#xA;func foo() Fooer {&#xA;    return S{true}&#xA;}&#xA;&#xA;func main() {&#xA;    f := foo()&#xA;    fmt.Printf(&amp;quot;Type: %T\n&amp;quot;, f) // main.S&#xA;    fmt.Printf(&amp;quot;Representation: %+v\n&amp;quot;, f) // {Debug:true}&#xA;    f.Bar()&#xA;    fmt.Println(f.Debug) // ERROR: f.Debug undefined (type Fooer has no field or method Debug)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the above code that we&amp;rsquo;re able to call the &lt;code&gt;Bar&lt;/code&gt; method (as it&amp;rsquo;s part of the public interface) but we can&amp;rsquo;t access the &lt;code&gt;Debug&lt;/code&gt; field, even though it&amp;rsquo;s declared as a public field.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how can we access the &lt;code&gt;Debug&lt;/code&gt; field? We need to use a &lt;a href=&#34;https://go.dev/tour/methods/15&#34; target=&#34;_blank&#34;&gt;type assertion&lt;/a&gt; to get access to the interface&amp;rsquo;s underlying value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;s, ok := f.(S)&#xA;if !ok {&#xA;  log.Fatal(&amp;quot;couldn&#39;t coerce f to S&amp;quot;)&#xA;}&#xA;fmt.Println(s.Debug) // true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is the &amp;lsquo;indirection&amp;rsquo; I was referring to, and is a tedious step for a consumer of this code. They wouldn&amp;rsquo;t need to do this if our &lt;code&gt;foo&lt;/code&gt; function had returned the concrete &lt;code&gt;S&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;don-t-return-concrete-types&#34;&gt;Don&amp;rsquo;t Return Concrete Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is to keep you on your toes 😉&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I want to highlight an important &amp;lsquo;design&amp;rsquo; decision, which is: if your code returns a pointer to some data, then it means once that pointer has been passed around a few different functions, we now have multiple entities that are able to mutate that data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So be careful about whether you return a value (immutable) vs a pointer (mutable) as it could help reduce confusion with regards to how the data is modified by your program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Returning an interface in these cases &lt;em&gt;could&lt;/em&gt; be an appropriate solution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;By this I mean&lt;/strong&gt;: although you might return a pointer to a data structure, by defining an interface around the behaviours attached to that data structure, it means a caller of your function won&amp;rsquo;t be able to access the internal fields of the struct but it &lt;em&gt;can&lt;/em&gt; call the methods defined in the returned interface!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another example might be that your function needs to return a different type depending on a runtime condition (&lt;code&gt;*cough* generics *cough*&lt;/code&gt;). If that&amp;rsquo;s the case, then returning an interface could again be an appropriate workaround to the lack of generics in the Go 1.x language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code example highlights the principle:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Itemer interface {&#xA;    GetItemValue() string&#xA;}&#xA;&#xA;type Item struct {&#xA;    ID int&#xA;}&#xA;&#xA;type URLItem struct {&#xA;    Item&#xA;    URL string&#xA;}&#xA;&#xA;type TextItem struct {&#xA;    Item&#xA;    Text string&#xA;}&#xA;&#xA;func (ui URLItem) GetItemValue(){&#xA;    return ui.URL&#xA;}&#xA;&#xA;func (ti TextItem) GetItemValue(){&#xA;    return ti.Text&#xA;}&#xA;&#xA;func FindItem(ID int) Itemer {&#xA;  // returns either a URLItem or a TextItem&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;FindItem&lt;/code&gt; could be an internal library function that attempts to locate an item via multiple data sources. Depending on which data source the item was found, the type returned will change.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this instance returning an interface allows the consumer to not have to worry about the change in underlying data types.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;It&amp;rsquo;s possible the returned types could be consolidated into a single generic type struct, which means we can avoid returning an interface, but it depends on the exact scenario/use case.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;use-existing-interfaces&#34;&gt;Use Existing Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to not &amp;lsquo;reinvent the wheel&amp;rsquo; and to utilise existing interfaces wherever possible (otherwise you&amp;rsquo;ll suffer from a condition known as &amp;lsquo;interface pollution&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The golang toolchain offers a tool called &lt;a href=&#34;https://docs.google.com/document/d/1_Y9xCEMj5S-7rv2ooHpZNH15JgRT5iM742gJkw5LtmQ/edit#heading=h.7q1t7o2y7td3&#34; target=&#34;_blank&#34;&gt;Go Guru&lt;/a&gt; which helps you to navigate Go code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s a command line tool, but it&amp;rsquo;s designed to be utilised from within an editor (like Atom or Vim etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a list of the sub commands available:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;callees         show possible targets of selected function call&#xA;callers         show possible callers of selected function&#xA;callstack       show path from callgraph root to selected function&#xA;definition      show declaration of selected identifier&#xA;describe        describe selected syntax: definition, methods, etc&#xA;freevars        show free variables of selection&#xA;implements      show &#39;implements&#39; relation for selected type or method&#xA;peers           show send/receive corresponding to selected channel op&#xA;pointsto        show variables the selected pointer may point to&#xA;referrers       show all refs to entity denoted by selected identifier&#xA;what            show basic information about the selected syntax node&#xA;whicherrs       show possible values of the selected error variable&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This can be really useful for identifying (for example) whether a new interface you&amp;rsquo;ve defined is similar to an existing interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To demonstrate this, consider the following example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// this is a duplicate of fmt.Stringer interface&#xA;type Stringer interface {&#xA;    String() string&#xA;}&#xA;&#xA;type testthing struct{}&#xA;&#xA;func (t testthing) String() string {&#xA;    return &amp;quot;a test thing&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;Stringer&lt;/code&gt; interface I&amp;rsquo;ve defined is actually a duplication of the existing standard library interface &lt;code&gt;fmt.Stringer&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So using Guru via my Vim editor I can see (when I have my cursor over the &lt;code&gt;testthing&lt;/code&gt; struct and I call Guru) that this concrete type implements not only &lt;code&gt;stringit&lt;/code&gt; but a few other interfaces&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/main.go:33.6-33.14:                                                 struct type testthing&#xA;/usr/local/Cellar/go/1.10.3/libexec/src/fmt/print.go:62.6-62.13:     implements fmt.Stringer&#xA;/main.go:29.6-29.13:                                                 implements Stringer&#xA;/usr/local/Cellar/go/1.10.3/libexec/src/runtime/error.go:66.6-66.13: implements runtime.stringer&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now whether you continue to define a new interface is up to you. There are actually quite a few places in the Go standard library where interfaces are duplicated for (what I believe to be) semantic reasoning, but otherwise if you don&amp;rsquo;t need to make an explicit/semantic distinction, then I&amp;rsquo;d opt to reuse an existing interface.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;For more details on how to use Guru, see &lt;a href=&#34;https://gist.github.com/Integralist/20ff7427d3df5cc02d5a619ca0cd9695&#34; target=&#34;_blank&#34;&gt;this gist&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;don-t-force-interfaces&#34;&gt;Don&amp;rsquo;t Force Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If your code doesn&amp;rsquo;t require interfaces, then don&amp;rsquo;t use them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;No point making the design of your code more complicated for no reason. Consider the following code which returns an interface.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;The following example is modified from a much older post by &lt;a href=&#34;https://www.ardanlabs.com/blog/2016/10/avoid-interface-pollution.html&#34; target=&#34;_blank&#34;&gt;William Kennedy&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;// Server defines a contract for tcp servers.&#xA;type Server interface {&#xA;    Start()&#xA;}&#xA;&#xA;type server struct{}&#xA;&#xA;// NewServer returns an interface value of type Server&#xA;func NewServer() Server {&#xA;    return &amp;amp;server{}&#xA;}&#xA;&#xA;// Start allows the server to begin to accept requests.&#xA;func (s *server) Start() {&#xA;    fmt.Println(&amp;quot;start called&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;    s := NewServer()&#xA;    fmt.Printf(&amp;quot;%+v (%T)\n&amp;quot;, s, s)&#xA;    s.Start()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The use of an interface here is a bit pointless. We should instead just return a pointer to an exported version of the server struct because the user is gaining no benefits from an interface being returned by &lt;code&gt;NewServer&lt;/code&gt; (see &lt;a href=&#34;#don-t-return-concrete-types&#34;&gt;Don&amp;rsquo;t Return Concrete Types&lt;/a&gt; for a possible use case for returning interfaces, but the above example is not one of them).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;⚠️ There is also an important performance consideration to using interfaces that is often neglected: method calls on an interface type will be using &lt;a href=&#34;https://en.wikipedia.org/wiki/Dynamic_dispatch&#34; target=&#34;_blank&#34;&gt;dynamic dispatch&lt;/a&gt; not &lt;a href=&#34;https://en.wikipedia.org/wiki/Static_dispatch&#34; target=&#34;_blank&#34;&gt;static dispatch&lt;/a&gt; and in a code hot path that can be a problem because the memory associated with the call can escape to the heap (stack memory is much more efficient). Consider &lt;code&gt;r&lt;/code&gt; had an interface type &lt;code&gt;io.Reader&lt;/code&gt;. A call to &lt;code&gt;r.Read(b)&lt;/code&gt; would result in both the value of &lt;code&gt;r&lt;/code&gt; and the backing array of the &lt;code&gt;b&lt;/code&gt; byte slice to be allocated onto the heap.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;embedding-interfaces&#34;&gt;Embedding Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Sometimes a code base will define a very large interface. Now we can probably agree it&amp;rsquo;s not a good idea but let&amp;rsquo;s just accept that in the real-world this kind of thing happens.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One place where a large interface can cause problems is with testing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a function accepts an interface but in reality only uses one method from the interface, then you might find yourself getting frustrated at the idea of having to implement a mock version of each method!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, to avoid that situation try taking advantage of Go&amp;rsquo;s ability to embed an interface into a struct.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By embedding the interface into your struct, you automatically &lt;em&gt;promote&lt;/em&gt; all of the methods to the embedding struct. Now, you can pass your mock struct to the function and the compiler will be happy. You now only need to implement the methods you need to assert the test scenario you&amp;rsquo;re trying to validate.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Exampler interface {&#xA;    Foo() error&#xA;    Bar() error&#xA;    Baz() error&#xA;    // ...lots more...&#xA;}&#xA;&#xA;func example(e Exampler) error {&#xA;  err := e.Foo()&#xA;  if err != nil {&#xA;    return err&#xA;  }&#xA;&#xA;  // ...other stuff...&#xA;&#xA;  return nil&#xA;}&#xA;&#xA;type mock struct{&#xA;  Example // embedded interface&#xA;}&#xA;&#xA;// We&#39;re only implementing one method, not all three!&#xA;func (m *mock) Foo() error {&#xA;  return errors.New(&amp;quot;whoops&amp;quot;)&#xA;}&#xA;&#xA;func TestExample(t *testing.T) {&#xA;    example(&amp;amp;mock{}) // we expect the function to fail due to our mock behaviour&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But be aware that because you&amp;rsquo;re not providing a concrete implementation of the interface when instantiating your struct, it means that the value of that embedded field will be &lt;code&gt;nil&lt;/code&gt;. This means that if the function you pass your struct into calls any of the interface methods &lt;em&gt;not&lt;/em&gt; implemented by your mock struct, then there will be a runtime &amp;lsquo;nil pointer dereference&amp;rsquo; error (but I argue that&amp;rsquo;s a good thing because in a test environment you want to know if your code is calling something for real).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;upgrading-interfaces&#34;&gt;Upgrading Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you use have an interface that&amp;rsquo;s used by lots of people, how do you add a new method to it without breaking their code? The moment you add a new method to the interface, their existing code that handles the concrete implementation will fail.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unfortunately there isn&amp;rsquo;t a completely clean solution to this problem. In essence the original interface needs to stay untouched and we need to define a &lt;em&gt;new&lt;/em&gt; interface that contains the new behaviour. Then the consumer&amp;rsquo;s of an interface will continue to reference the original interface while using a type assertion within their functions for the new interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of this problem in action:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Fooer interface {&#xA;    bar() string&#xA;    baz() string // new method added, which breaks the code&#xA;}&#xA;&#xA;func doThing(f Fooer) {&#xA;    fmt.Println(&amp;quot;bar:&amp;quot;, f.bar())&#xA;}&#xA;&#xA;type point struct {&#xA;    X, Y int&#xA;}&#xA;&#xA;func (p point) bar() string {&#xA;    return fmt.Sprintf(&amp;quot;p=%d, y=%d&amp;quot;, p.X, p.Y)&#xA;}&#xA;&#xA;func main() {&#xA;    var pt point&#xA;    pt.X = 1&#xA;    pt.Y = 2&#xA;&#xA;    doThing(pt)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above code we can see we have added a new method &lt;code&gt;baz&lt;/code&gt; to our &lt;code&gt;Fooer&lt;/code&gt; interface which means the concrete implementation &lt;code&gt;pt&lt;/code&gt; is no longer satisfying the &lt;code&gt;Fooer&lt;/code&gt; interface as it has no &lt;code&gt;baz&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I appreciate the example is a bit silly because we could just update the code to support the new interface, but we have to imagine a world where your interface is provided as part of a public package that is consumed by lots of users.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To solve this problem we need an intermediate interface. The following example demonstrates the process. The steps are&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;define a new interface containing the new method&lt;/li&gt;&#xA;&lt;li&gt;add the method to the concrete type implementation&lt;/li&gt;&#xA;&lt;li&gt;document the new interface and ask your interface consumers to type assert for it&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Fooer interface {&#xA;    bar() string&#xA;}&#xA;&#xA;type Newfooer interface {&#xA;    baz() string&#xA;}&#xA;&#xA;// We want a `Fooer` interface type, but if that valid type can also do the new&#xA;// behaviour, then we&#39;ll execute that behaviour...&#xA;&#xA;func doThing(f Fooer) {&#xA;    if nf, ok := f.(Newfooer); ok {&#xA;        fmt.Println(&amp;quot;baz:&amp;quot;, nf.baz())&#xA;    }&#xA;    fmt.Println(&amp;quot;bar:&amp;quot;, f.bar())&#xA;}&#xA;&#xA;// Original concrete implementation...&#xA;&#xA;type point struct {&#xA;    X, Y int&#xA;}&#xA;&#xA;func (p point) bar() string {&#xA;    return fmt.Sprintf(&amp;quot;p=%d, y=%d&amp;quot;, p.X, p.Y)&#xA;}&#xA;&#xA;// New concrete implementation of `point` struct (has the new method)...&#xA;&#xA;type newpoint struct {&#xA;    point&#xA;}&#xA;&#xA;func (np newpoint) baz() string {&#xA;    return fmt.Sprintf(&amp;quot;np !!! %d, ny !!! %d&amp;quot;, np.X, np.Y)&#xA;}&#xA;&#xA;func main() {&#xA;    var pt point&#xA;    pt.X = 1&#xA;    pt.Y = 2&#xA;&#xA;    doThing(pt)&#xA;&#xA;    var npt newpoint&#xA;    npt.X = 3&#xA;    npt.Y = 4&#xA;&#xA;    doThing(npt)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Again, the example is a bit silly in that we&amp;rsquo;re handling everything within a single file, whereas in reality the consumer won&amp;rsquo;t have access to the original interface/implementation code like we do here (so just use your imagination 🙂).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The output of the above code is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bar: p=1, y=2&#xA;baz: np !!! 3, ny !!! 4&#xA;bar: p=3, y=4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see we called &lt;code&gt;doThing&lt;/code&gt; and passed a concrete type that satisfied the &lt;code&gt;Fooer&lt;/code&gt; interface and so that function called the &lt;code&gt;bar&lt;/code&gt; method it was expecting to exist. Next we called &lt;code&gt;doThing&lt;/code&gt; again but passed a different concrete type that not only satisfied the &lt;code&gt;Fooer&lt;/code&gt; interface, but the &lt;code&gt;Newfooer&lt;/code&gt; interface and within &lt;code&gt;doThing&lt;/code&gt; we type assert that the object passed in is not only a &lt;code&gt;Fooer&lt;/code&gt; but a &lt;code&gt;Newfooer&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What would this look like in practice then? Well, if the Go standard library wanted to add a new method to the existing (and very popular) &lt;code&gt;net/http&lt;/code&gt; package &lt;code&gt;ResponseWriter&lt;/code&gt; interface: they would create a new interface with just the new behaviour defined, then they would document its existence and in that documentation they would explain that if your HTTP handler required the new behaviour, then you should type assert for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine if the go standard library just updated the &lt;code&gt;ResponseWriter&lt;/code&gt; with the new method? Lots and lots of existing HTTP server code would break as the concrete implementation that was passed through would not support that implementation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In fact this is exactly what the go standard library authors have done with the &lt;a href=&#34;https://golang.org/pkg/net/http/#Flusher&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Flusher&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://golang.org/pkg/net/http/#Hijacker&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Hijacker&lt;/code&gt;&lt;/a&gt; interfaces. The following code demonstrates the use of a type assertion to access the additional behaviour defined by those interfaces:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func(w http.ResponseWriter, r *http.Request) {&#xA;        io.WriteString(w, &amp;quot;This will arrive before... &amp;quot;)&#xA;&#xA;        if fl, ok := w.(http.Flusher); ok {&#xA;                fl.Flush()&#xA;                time.Sleep(1 * time.Second)&#xA;        }&#xA;&#xA;        io.WriteString(w, &amp;quot;...this bit does.&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;standard-library-interfaces&#34;&gt;Standard Library Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine we have a function &lt;code&gt;process&lt;/code&gt;, whose responsibility is to make a HTTP request and do something with the response data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;func process(n int) (string, error) {&#xA;    url := fmt.Sprintf(&amp;quot;http://httpbin.org/links/%d/0&amp;quot;, n)&#xA;&#xA;    resp, err := http.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;url get error: %s\n&amp;quot;, err)&#xA;        return &amp;quot;&amp;quot;, err&#xA;    }&#xA;&#xA;    defer resp.Body.Close()&#xA;&#xA;    body, err := ioutil.ReadAll(resp.Body)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;body read error: %s\n&amp;quot;, err)&#xA;        return &amp;quot;&amp;quot;, err&#xA;    }&#xA;&#xA;    return string(body), nil&#xA;}&#xA;&#xA;func main() {&#xA;    data, err := process(5)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;\ndata processing error: %s\n&amp;quot;, err)&#xA;        return&#xA;    }&#xA;    fmt.Printf(&amp;quot;Success: %v&amp;quot;, data)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see our &lt;code&gt;process&lt;/code&gt; function accepts an integer, which is interpolated into the URL that is requested. We then use the &lt;code&gt;http.Get&lt;/code&gt; function from the &lt;a href=&#34;https://golang.org/pkg/net/http/&#34; target=&#34;_blank&#34;&gt;net/http&lt;/a&gt; package to request the URL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The function then stringify&amp;rsquo;s the response body and returns it. This is sufficient for a basic example, but in the real world this function would likely do lots more processing to the response data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It may not be immediately obvious but there are already many instances where interfaces are being utilised. Let&amp;rsquo;s break down the code and see what interfaces there are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;http.Get&lt;/code&gt; function returns a pointer to a &lt;code&gt;http.Response&lt;/code&gt; struct, and from within that struct we extract the &lt;code&gt;Body&lt;/code&gt; field and pass it to &lt;code&gt;ioutil.ReadAll&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;Body&lt;/code&gt; field&amp;rsquo;s &amp;lsquo;type&amp;rsquo; is set to the &lt;a href=&#34;https://golang.org/src/io/io.go?s=4977:5022#L116&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;io.ReadCloser&lt;/code&gt;&lt;/a&gt; interface. If we look at that interface we&amp;rsquo;ll see it&amp;rsquo;s made up of &lt;em&gt;nested&lt;/em&gt; interface types:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type ReadCloser interface {&#xA;    Reader&#xA;    Closer&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we now look at the &lt;a href=&#34;https://golang.org/src/io/io.go?s=3303:3363#L67&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;io.Reader&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://golang.org/src/io/io.go?s=4043:4083#L88&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;io.Closer&lt;/code&gt;&lt;/a&gt; interfaces, we&amp;rsquo;ll find:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Reader interface {&#xA;    Read(p []byte) (n int, err error)&#xA;}&#xA;&#xA;type Closer interface {&#xA;    Close() error&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This means that for the response body object to be valid, it must support the &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Close&lt;/code&gt; functions defined by these interfaces (the returned object will likely include other functions, but it needs &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Close&lt;/code&gt; at a minimum).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next thing that happens in the code is that we pass &lt;code&gt;http.Response.Body&lt;/code&gt; to an input/output function called &lt;code&gt;ioutil.ReadAll&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at the signature of &lt;code&gt;ioutil.ReadAll&lt;/code&gt; we&amp;rsquo;ll see that it accepts a type of &lt;code&gt;io.Reader&lt;/code&gt;, which we&amp;rsquo;ve seen already, and so this is another indication of why smaller interfaces enable re-usability.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What the &lt;code&gt;io.Reader&lt;/code&gt; interface means for our code is that the input we provide to &lt;code&gt;ioutil.ReadAll&lt;/code&gt; must support a &lt;code&gt;Read&lt;/code&gt; function, and (because &lt;code&gt;http.Response.Body&lt;/code&gt; implements the &lt;code&gt;io.ReadCloser&lt;/code&gt; interface) we know it does implement that required function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So already we&amp;rsquo;ve seen quite a few built-in interfaces being utilised to support the standard library code we&amp;rsquo;re using. More importantly, you&amp;rsquo;ll find the use of these interfaces (&lt;code&gt;io.ReadCloser&lt;/code&gt;, &lt;code&gt;io.Reader&lt;/code&gt;, &lt;code&gt;io.Closer&lt;/code&gt; and others) are used &lt;em&gt;everywhere&lt;/em&gt; in the Go codebase (highlighting again how small interfaces enable greater code re-usability).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tight-coupling&#34;&gt;Tight Coupling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now there&amp;rsquo;s an issue with the above code, specifically the &lt;code&gt;process&lt;/code&gt; function, and that is we&amp;rsquo;ve tightly coupled the &lt;code&gt;net/http&lt;/code&gt; package to the function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What this means is that the &lt;code&gt;process&lt;/code&gt; function has to intrinsically &lt;em&gt;know&lt;/em&gt; about HTTP and dealing with the various methods available to that package.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, if we want to test this function we&amp;rsquo;re going to have a harder time because the &lt;code&gt;http.Get&lt;/code&gt; call would need to be mocked somehow. We don&amp;rsquo;t want our test suite to have to rely on a stable network connection or the fact that the endpoint being requested might be down for maintenance.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution to this problem is to invert the responsibility of the &lt;code&gt;process&lt;/code&gt; function, also known as &amp;lsquo;dependency injection&amp;rsquo;. This is the basis of one of the &lt;a href=&#34;https://en.wikipedia.org/wiki/SOLID&#34; target=&#34;_blank&#34;&gt;S.O.L.I.D&lt;/a&gt; principles: &amp;lsquo;inversion of control&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dependency-injection&#34;&gt;Dependency Injection&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If we call a function, then it is our responsibility to provide it with all the things it needs in order to do its job.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of our &lt;code&gt;process&lt;/code&gt; function, it needs to be able to acquire data from somewhere (that could be a file, it could be a remote procedure call, it shouldn&amp;rsquo;t matter). The most important aspect to consider is &lt;em&gt;how&lt;/em&gt; it acquires that data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;em&gt;how&lt;/em&gt; is not the responsibility of the &lt;code&gt;process&lt;/code&gt; function, especially if we decide later on that we want to change the implementation from HTTP to GRPC or some other data source.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning, we need to provide that functionality to the &lt;code&gt;process&lt;/code&gt; function. Let&amp;rsquo;s see what this might look like in practice:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;This is just a first iteration, and is a poor design because although it shifts the problem slightly, there will still be tight coupling. I&amp;rsquo;ll come back to this code later and refactor away the coupling completely. The reason I&amp;rsquo;ve not done that upfront is because there are learnings to be had from trying to write tests for this code (which we&amp;rsquo;ll see in a minute).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type Getter interface {&#xA;    Get(url string) (*http.Response, error)&#xA;}&#xA;&#xA;type httpbin struct{}&#xA;&#xA;func (l *httpbin) Get(url string) (*http.Response, error) {&#xA;    resp, err := http.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;url get error: %s\n&amp;quot;, err)&#xA;        return &amp;amp;http.Response{}, err&#xA;    }&#xA;&#xA;    return resp, nil&#xA;}&#xA;&#xA;func process(n int, g Getter) (string, error) {&#xA;    url := fmt.Sprintf(&amp;quot;http:/httpbin.org/links/%d/0&amp;quot;, n)&#xA;&#xA;    resp, err := g.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;data source get error: %s\n&amp;quot;, err)&#xA;        return &amp;quot;&amp;quot;, err&#xA;    }&#xA;&#xA;    defer resp.Body.Close()&#xA;&#xA;    body, err := ioutil.ReadAll(resp.Body)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;body read error: %s\n&amp;quot;, err)&#xA;        return &amp;quot;&amp;quot;, err&#xA;    }&#xA;&#xA;    return string(body), nil&#xA;}&#xA;&#xA;func main() {&#xA;    data, err := process(5, &amp;amp;httpbin{})&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;\ndata processing error: %s\n&amp;quot;, err)&#xA;        return&#xA;    }&#xA;    fmt.Printf(&amp;quot;\nSuccess: %v\n&amp;quot;, data)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;refactoring-considerations&#34;&gt;Refactoring Considerations&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start by looking at the interface we&amp;rsquo;ve defined:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Getter interface {&#xA;    Get(url string) (*http.Response, error)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve not been overly explicit when naming this interface &lt;code&gt;Getter&lt;/code&gt;. Its name is quite generic on purpose so as not to imply an underlying implementation bias.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unfortunately the defined &lt;code&gt;Get&lt;/code&gt; method is still too tightly coupled to a specific implementation (i.e. it specifies &lt;code&gt;http.Response&lt;/code&gt; as a return type).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning, that although the refactored code is &lt;em&gt;better&lt;/em&gt;, it is far from perfect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we define our own object for handling the implementation of the &lt;code&gt;Get&lt;/code&gt; method, which internally is going to use &lt;code&gt;http.Get&lt;/code&gt; to acquire the data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type httpbin struct{}&#xA;&#xA;func (l *httpbin) Get(url string) (*http.Response, error) {&#xA;    resp, err := http.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;url get error: %s\n&amp;quot;, err)&#xA;        return &amp;amp;http.Response{}, err&#xA;    }&#xA;&#xA;    return resp, nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;By using this interface as the accepted type in the &lt;code&gt;process&lt;/code&gt; function signature, we&amp;rsquo;re going to be able to decouple the function from having to acquire the data, and thus allow testing to become much easier (as we&amp;rsquo;ll see shortly), but the &lt;code&gt;process&lt;/code&gt; function is still fundamentally coupled to HTTP as the underlying transport mechanism.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this is a problem is because the &lt;code&gt;process&lt;/code&gt; function still &lt;em&gt;knows&lt;/em&gt; that the returned object is a &lt;code&gt;http.Response&lt;/code&gt; because it has to reference the &lt;code&gt;Body&lt;/code&gt; field of the response, which isn&amp;rsquo;t defined on the object we&amp;rsquo;ve injected (meaning the function intrinsically &lt;em&gt;knows&lt;/em&gt; of its existence).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How far you take your interface design is up to you. You don&amp;rsquo;t necessarily have to solve all possible concerns at once (unless there really is a need to do so).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning, this refactor &lt;em&gt;could&lt;/em&gt; be considered &amp;lsquo;good enough&amp;rsquo; for your use cases. Alternatively your values and standards may differ, and so you need to consider your options for how you might what to design this solution in such a way that it would allow the code to not be so reliant on HTTP as the transport mechanism.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ll revisit this code later and consider another refactor that will help clean up this first pass of code decoupling.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But first, let&amp;rsquo;s look at how we might want to test this initial code refactor (as testing this code allows us to learn some interesting things when it comes to needing to mock interfaces).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is a simple test suite that demonstrates how we&amp;rsquo;re now able to construct our own object, with a stubbed response, and pass that to the &lt;code&gt;process&lt;/code&gt; function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;bytes&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;testing&amp;quot;&#xA;)&#xA;&#xA;type fakeHTTPBin struct{}&#xA;&#xA;func (l *fakeHTTPBin) Get(url string) (*http.Response, error) {&#xA;    body := &amp;quot;Hello World&amp;quot;&#xA;&#xA;    resp := &amp;amp;http.Response{&#xA;        Body:          ioutil.NopCloser(bytes.NewBufferString(body)),&#xA;        ContentLength: int64(len(body)),&#xA;        StatusCode:    http.StatusOK,&#xA;        Request:       &amp;amp;http.Request{},&#xA;    }&#xA;&#xA;    return resp, nil&#xA;}&#xA;&#xA;func TestBasics(t *testing.T) {&#xA;    expect := &amp;quot;Hello World&amp;quot;&#xA;    actual, _ := process(5, &amp;amp;fakeHTTPBin{})&#xA;&#xA;    if actual != expect {&#xA;        t.Errorf(&amp;quot;expected %s, actual %s&amp;quot;, expect, actual)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Much like we do in the real implementation, we define a struct (in this case we&amp;rsquo;ve named it more explicitly) &lt;code&gt;fakeHTTPBin&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The difference now, and what allows us to test our code is that we&amp;rsquo;re manually creating a &lt;code&gt;http.Response&lt;/code&gt; object with dummy data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One part of this code that requires some extra explanation would be the value assigned to the response &lt;code&gt;Body&lt;/code&gt; field:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;ioutil.NopCloser(bytes.NewBufferString(body))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we remember from earlier:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The &lt;code&gt;Body&lt;/code&gt; field&amp;rsquo;s &amp;lsquo;type&amp;rsquo; is set to the &lt;code&gt;io.ReadCloser&lt;/code&gt; interface.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This means when mocking the &lt;code&gt;Body&lt;/code&gt; value we need to return something that has both a &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Close&lt;/code&gt; method. So we&amp;rsquo;ve used &lt;code&gt;ioutil.NopCloser&lt;/code&gt; which, if we look at its signature, we see returns an &lt;code&gt;io.ReadCloser&lt;/code&gt; interface:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func NopCloser(r io.Reader) io.ReadCloser&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;io.ReadCloser&lt;/code&gt; interface is exactly what we need (as that interface indicates the returned concrete type will indeed implement the required &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Close&lt;/code&gt; methods).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But to use it we need to provide the &lt;code&gt;NopCloser&lt;/code&gt; function something that supports the &lt;code&gt;io.Reader&lt;/code&gt; interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we were to provide a simple string like &lt;code&gt;&amp;quot;Hello World&amp;quot;&lt;/code&gt;, then this wouldn&amp;rsquo;t implement the required interface. So we wrap the string in a call to &lt;code&gt;bytes.NewBufferString&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we do this is because the returned type is something that supports the &lt;code&gt;io.Reader&lt;/code&gt; interface we need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But that might not be immediately obvious when looking at the signature for &lt;code&gt;bytes.NewBufferString&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func NewBufferString(s string) *Buffer&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So yes it accepts a string, but we want an &lt;code&gt;io.Reader&lt;/code&gt; as the return type, whereas this function returns a pointer to a &lt;a href=&#34;https://golang.org/src/bytes/buffer.go?s=402:817#L7&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;Buffer&lt;/code&gt;&lt;/a&gt; type?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at the implementation of &lt;code&gt;Buffer&lt;/code&gt; though, we will see that it does actually &lt;a href=&#34;https://golang.org/src/bytes/buffer.go?s=9564:9614#L287&#34; target=&#34;_blank&#34;&gt;implement&lt;/a&gt; the required &lt;code&gt;Read&lt;/code&gt; function necessary to support the &lt;code&gt;io.Reader&lt;/code&gt; interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Great! Our test can now call the &lt;code&gt;process&lt;/code&gt; function and process the mocked dependency and the code/test works as intended.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Yes, we should probably use something more obvious and replace &lt;code&gt;bytes.NewBufferString&lt;/code&gt; with something like &lt;code&gt;bytes.NewReader&lt;/code&gt;, &lt;code&gt;strings.NewReader&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;more-flexible-solutions&#34;&gt;More flexible solutions?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so we&amp;rsquo;ve already explained why this implementation might not be the best we could do. Let&amp;rsquo;s now consider an alternative implementation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type Getter interface {&#xA;    Get(url string) ([]byte, error)&#xA;}&#xA;&#xA;type httpbin struct{}&#xA;&#xA;func (l *httpbin) Get(url string) ([]byte, error) {&#xA;    resp, err := http.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;url get error: %s\n&amp;quot;, err)&#xA;        return []byte{}, err&#xA;    }&#xA;&#xA;    defer resp.Body.Close()&#xA;&#xA;    body, err := ioutil.ReadAll(resp.Body)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;body read error: %s\n&amp;quot;, err)&#xA;        return []byte{}, err&#xA;    }&#xA;&#xA;    return body, nil&#xA;}&#xA;&#xA;func process(n int, g Getter) (string, error) {&#xA;    url := fmt.Sprintf(&amp;quot;http://httpbin.org/links/%d/0&amp;quot;, n)&#xA;&#xA;    resp, err := g.Get(url)&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;data source get error: %s\n&amp;quot;, err)&#xA;        return &amp;quot;&amp;quot;, err&#xA;    }&#xA;&#xA;    return string(resp), nil&#xA;}&#xA;&#xA;func main() {&#xA;    data, err := process(5, &amp;amp;httpbin{})&#xA;    if err != nil {&#xA;        fmt.Printf(&amp;quot;\ndata processing error: %s\n&amp;quot;, err)&#xA;        return&#xA;    }&#xA;    fmt.Printf(&amp;quot;\nSuccess: %v\n&amp;quot;, data)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;All we&amp;rsquo;ve really done here is move more of the logic related to HTTP up into the &lt;code&gt;httpbin.Get&lt;/code&gt; implementation of the &lt;code&gt;Getter&lt;/code&gt; interface. We&amp;rsquo;ve also changed the response type from &lt;code&gt;(*http.Response, error)&lt;/code&gt; to &lt;code&gt;([]byte, error)&lt;/code&gt; to account for these movements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the &lt;code&gt;process&lt;/code&gt; function has even &lt;em&gt;less&lt;/em&gt; responsibility as far as acquiring data is concerned. This also means our test suite benefits by having a much simpler implementation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import &amp;quot;testing&amp;quot;&#xA;&#xA;type fakeHTTPBin struct{}&#xA;&#xA;func (l *fakeHTTPBin) Get(url string) ([]byte, error) {&#xA;    return []byte(&amp;quot;Hello World&amp;quot;), nil&#xA;}&#xA;&#xA;func TestBasics(t *testing.T) {&#xA;    expect := &amp;quot;Hello World&amp;quot;&#xA;    actual, _ := process(5, &amp;amp;fakeHTTPBin{})&#xA;&#xA;    if actual != expect {&#xA;        t.Errorf(&amp;quot;expected %s, actual %s&amp;quot;, expect, actual)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now our &lt;code&gt;fakeHTTPBin.Get&lt;/code&gt; only has to return a byte array.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Is there more we can do to improve this code&amp;rsquo;s design? Sure. But we&amp;rsquo;ll leave a new refactor iteration to another post.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hopefully this has given you a feeling for how interfaces are used in the Go standard library and how you might utilise custom interfaces yourself.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-interfaces/</guid>
      <link>https://www.integralist.co.uk/posts/go-interfaces/</link>
      <pubDate>Sat, 21 Jul 2018 00:00:00 +0000</pubDate>
      <title>Thinking about Interfaces in Go</title>
    </item>
    <item>
      <description>&lt;p&gt;It seems most people are either talking about &amp;ldquo;monolith applications&amp;rdquo; or &amp;ldquo;micro services&amp;rdquo;. But recently I&amp;rsquo;ve noticed yet another new buzzword bubbling up across the internet: &amp;ldquo;mini services&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth mentioning that this &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; a post about which pattern is the most appropriate to use, as they&amp;rsquo;re &lt;em&gt;all&lt;/em&gt; appropriate to use, when applied in the right context and scenario.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an image that visualises the concept, and makes understanding these various patterns much easier (at a glance):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/multigrain-services.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/multigrain-services.png&#34; alt=&#34;multigrain services&#34; /&gt;&lt;/a&gt;&#xA;&lt;center&gt;&lt;small&gt;&lt;a href=&#34;https://thenewstack.io/miniservices-a-realistic-alternative-to-microservices/&#34; target=&#34;_blank&#34;&gt;source: thenewstack.io&lt;/a&gt;&lt;/small&gt;&lt;/center&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;a-rose-by-any-other-name&#34;&gt;A rose by any other name&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To me &amp;ldquo;mini services&amp;rdquo; isn&amp;rsquo;t anything new, nor do I think it necessarily needs a new term to be applied to it. For me &amp;ldquo;mini services&amp;rdquo; are effectively just &lt;a href=&#34;https://en.wikipedia.org/wiki/Service-oriented_architecture&#34; target=&#34;_blank&#34;&gt;SOA&lt;/a&gt; (Service Oriented Architecture), but done right.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People complain about SOA and say it has lots of pain points that make it unusable. I disagree. From what I&amp;rsquo;ve read it simply comes down to designing your SOA correctly so that it has proper fault tolerance and resiliency. Not just throwing together some code, seeing certain dependencies break and then crying that SOA is rubbish 🤦‍♂️&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although maybe a new services lexicon † &lt;em&gt;is&lt;/em&gt; useful, at least for giving a consistent and modern terminology to these concepts we collectively understand.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† the vocabulary of a person, language, or branch of knowledge.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;definitions&#34;&gt;Definitions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s breakdown these concepts along with their old/new terminology:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Macro Service&lt;/strong&gt; (Monolith Application): the traditional architecture model/system design. One big application handling multiple responsibilities and all of them plugged into a single data store.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mini Service&lt;/strong&gt; (SOA): an evolution of the monolith where domain &amp;lsquo;boundaries&amp;rsquo; were more clearly defined and made into &lt;em&gt;separate&lt;/em&gt; services and data stores. Although these services would still handle multiple responsibilities, those responsibilties were at least &lt;em&gt;related&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Micro Service&lt;/strong&gt;: we breakdown the domain boundaries even further so that services/data stores have very narrow and specific responsibilties. We&amp;rsquo;ve moved to &amp;lsquo;feature driven&amp;rsquo; services.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nano Service&lt;/strong&gt;: we go to the extremes of boundary definitions and are working at the &amp;lsquo;component&amp;rsquo; level (BBC explain their approach to this &lt;a href=&#34;https://medium.com/bbc-design-engineering/powering-bbc-online-with-nanoservices-727840ba015b&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Micro services are themselves a new&amp;rsquo;ish concept at ~7 years of age (at the time of writing). The term was first used in 2011.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;real-micro-services&#34;&gt;Real micro services?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Martin Fowler famously defined microservices as having a very specific design application and that most &amp;ldquo;micro services&amp;rdquo; aren&amp;rsquo;t conforming to that. Specifically he says that they should:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Have a single responsibility&lt;/li&gt;&#xA;&lt;li&gt;Be loosely coupled&lt;/li&gt;&#xA;&lt;li&gt;Be independently deployable and scalable&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;But according to Ross Garrett (VP of Marketing Cloud Elements): &amp;ldquo;an HTTP-build service has to know more about what’s going on around it in order to communicate&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how do we achieve communication without relying on tried and tested HTTP/REST APIs etc? The answer is the &amp;lsquo;observer&amp;rsquo; design pattern (or pub/sub - publisher, subscriber model).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With the pub/sub model, the micro service publishes notifications whenever something happens and services can subscribe to those notifications. This means the micro service has no awareness of anything outside of itself, it just throws out a notification and there&amp;rsquo;s either someone there to catch it and process it, or there isn&amp;rsquo;t.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Queue systems like RabbitMQ or SQS etc are used heavily in these cases to allow for that decoupling.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;what-do-you-use&#34;&gt;What do you use?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I tend to gravitate towards the SOA pattern † as it&amp;rsquo;s a nice balance between loose coupling and separation of domain boundaries without descending into the co-ordination and infrastructure madness of micro services.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† or &amp;ldquo;mini services&amp;rdquo; if that&amp;rsquo;s the language you prefer, although I personally don&amp;rsquo;t think I&amp;rsquo;ll ever be able to bring myself to use it over &amp;ldquo;SOA&amp;rdquo;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/multigrain-services/</guid>
      <link>https://www.integralist.co.uk/posts/multigrain-services/</link>
      <pubDate>Thu, 19 Jul 2018 00:00:00 +0000</pubDate>
      <title>Multigrain Services</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In this post I would like to introduce you to the &lt;a href=&#34;https://aws.amazon.com/cognito/&#34; target=&#34;_blank&#34;&gt;AWS&#xA;Cognito&lt;/a&gt; service, and to explain its various&#xA;moving pieces and how they fit together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in a very high-level view of what I was working on, then&#xA;&lt;a href=&#34;#updated-architecture&#34;&gt;this architecture diagram&lt;/a&gt; should give you the basic&#xA;idea.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Effectively I co-designed and implemented a new authentication system (using AWS&#xA;Cognito) for BuzzFeed&amp;rsquo;s existing community users to utilize and which opened the&#xA;doors for new BuzzFeed services to also be able to offer additional features&#xA;built upon authentication to their users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Cognito is tricky to get up and running with (for a variety of reasons which&#xA;I&amp;rsquo;ll explain as we go), and to make things worse there aren&amp;rsquo;t many reference&#xA;points outside of the official documentation to help you. Hence this blog post&#xA;now exists for those weary travellers looking for answers.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this post was written approximately five months into a year long project&#xA;and so a lot has changed in the design of the system and the implementation.&#xA;But this post is still very relevant and useful for those looking to&#xA;understand Cognito. This post also was fed back to various internal AWS teams&#xA;and has resulted in work being carried out to improve various aspects of their&#xA;services mentioned here.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start at the beginning&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-cognito&#34;&gt;What is Cognito?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;According to &lt;a href=&#34;https://aws.amazon.com/cognito/&#34; target=&#34;_blank&#34;&gt;the official blurb&lt;/a&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Amazon Cognito lets you add user sign-up, sign-in, and access control to your&#xA;web and mobile apps quickly and easily.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In essence, Cognito provides features that let you &lt;em&gt;authenticate&lt;/em&gt; access to your&#xA;services, while also providing features to let you &lt;em&gt;authorize&lt;/em&gt; access to your&#xA;AWS resources.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;authentication-vs-authorization&#34;&gt;Authentication vs Authorization&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to clarify that in this blog post we&amp;rsquo;re only really discussing&#xA;authentication, and not &lt;em&gt;authorization&lt;/em&gt;. They are two different concepts.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt; is the process of verification that an individual, entity&#xA;or website is who it claims to be.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authorization&lt;/strong&gt; is the function of specifying access rights to resources,&#xA;which is different to (and commonly confused with) the process of&#xA;authentication.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re new to these types of security concepts, then take a look at&#xA;&lt;a href=&#34;https://docs.google.com/document/d/1qs3jEIQvocdVhSxCSPLF1BoLnp91aLnuUIasvl-maYo/edit#&#34; target=&#34;_blank&#34;&gt;this glossary&#xA;document&lt;/a&gt;&#xA;I put together which covers the various terminology.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;user-pools-vs-identity-pools&#34;&gt;User Pools vs Identity Pools&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order for you to be able to &lt;em&gt;authenticate&lt;/em&gt; and &lt;em&gt;authorize&lt;/em&gt; access, Cognito&#xA;provides two separate services:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;User Pools&lt;/li&gt;&#xA;&lt;li&gt;Identity Pools&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;User Pools deal with &amp;lsquo;authentication&amp;rsquo;, whereas Identity Pools deal with&#xA;&amp;lsquo;authorization&amp;rsquo; (and specifically that means AWS based resources only).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the purposes of this post I&amp;rsquo;ll only be focusing in on User Pools, as our&#xA;project requirements did not involve authorizing access for AWS resources to an&#xA;authenticated user (which is where Identity Pools would typically come into&#xA;play).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, with &lt;em&gt;that&lt;/em&gt; said (and what makes this oh the more confusing, due to the&#xA;design of the mobile SDKs), mobile applications do utilize Identity Pools for&#xA;authentication, but the Identity Pool would be configured with a &amp;lsquo;provider&amp;rsquo;&#xA;which happened to be our User Pool.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in the various Identity Pool concepts, then please refer&#xA;to &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html&#34; target=&#34;_blank&#34;&gt;the official&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;implementation-options&#34;&gt;Implementation Options&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are fundamentally three options available for implementing User Pools:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Client SDK&lt;/li&gt;&#xA;&lt;li&gt;Server SDK&lt;/li&gt;&#xA;&lt;li&gt;AWS Hosted UI&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;client-sdk&#34;&gt;Client SDK&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The client SDK has a bit of a jagged history, which makes reading the AWS docs a&#xA;bit confusing at times (or indeed when Googling for help), as you may notice&#xA;references to &amp;lsquo;&lt;a href=&#34;https://github.com/amazon-archives/amazon-cognito-identity-js&#34; target=&#34;_blank&#34;&gt;Amazon Cognito Identity SDK for&#xA;JavaScript&lt;/a&gt;&amp;rsquo;&#xA;which is now a deprecated library.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What you&amp;rsquo;ll want to use instead is their new&#xA;&amp;lsquo;&lt;a href=&#34;https://aws.github.io/aws-amplify/&#34; target=&#34;_blank&#34;&gt;Amplify&lt;/a&gt;&amp;rsquo; SDK, which you&amp;rsquo;ll also find AWS&#xA;has a strong bias towards (or at least their &amp;lsquo;solution architects&amp;rsquo; push it&#xA;&lt;em&gt;really&lt;/em&gt; hard).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I get the feeling AWS put a lot more time into Amplify and having it be&#xA;able to abstract away a lot of the Cognito complexity, that they&amp;rsquo;re keen for&#xA;consumers to utilise it.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Based on this I decided I would trust their opinion and just try and spin up&#xA;something that works using Amplify, which unfortunately took a long time and&#xA;ultimately I ended up dropping the work in favour of a server-side solution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t keep up with the constant changes to the JavaScript landscape, and so&#xA;I&amp;rsquo;m not familiar with React (or Angular) which were the two examples the AWS&#xA;docs (and most example repos) used the majority of the time. So using Amplify&#xA;required me to first do some reading up on React, Babel, WebPack and a whole&#xA;host of other tools. It was painful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the end we just had too much trouble trying to deal with Node and the various&#xA;build systems that we decided to drop the work we had done and pivot to a new&#xA;solution (see next section).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;server-sdk&#34;&gt;Server SDK&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The server-side solution we chose was to use the &lt;a href=&#34;https://boto3.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;Python&#xA;SDK&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This ended up being a bit of a double edged sword. We were happier with the move&#xA;to Python, but we really struggled with both the AWS documentation and also the&#xA;boto3 library documentation that the Python SDK is built upon.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to get up and running we initially opted to use a 3rd party abstraction&#xA;library called &amp;lsquo;&lt;a href=&#34;https://github.com/capless/warrant&#34; target=&#34;_blank&#34;&gt;Warrant&lt;/a&gt;&amp;rsquo;, which also&#xA;incidentally helped us to understand the AWS documentation because we were able&#xA;to reverse-engineer the Warrant code to better understand the boto3 API calls&#xA;that needed to be made.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I think that says a lot about AWS documentation. If people need to read&#xA;through how an abstraction library is using your API, then your documentation&#xA;must be pretty bad. I would be the first to suggest maybe I&amp;rsquo;m just too dumb to&#xA;understand Cognito, but a &lt;em&gt;lot&lt;/em&gt; of people across the internet were having the&#xA;same problems.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Ultimately, Warrant didn&amp;rsquo;t provide all the functionality we needed and so we&#xA;eventually refactored out Warrant and were back to using the underlying boto3&#xA;Python SDK.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth me taking a moment to also explain that some APIs require you to&#xA;define a specific type of &amp;lsquo;authentication flow&amp;rsquo; which is a security feature, and&#xA;as far as I understand it, is supposed to help you to more safely access data&#xA;provided by these APIs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What I didn&amp;rsquo;t know originally, and was one of the reasons we decided to use a&#xA;library such as Warrant, was that the code involved with some of these auth&#xA;flows can be quite complex (I still now struggle to follow exactly what the code&#xA;does within Warrant when it uses one of these &amp;lsquo;flows&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Just to give you an example of the type of code AWS Cognito would expect you to&#xA;write, take a look at the&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;InitiateAuth&lt;/code&gt;&lt;/a&gt;&#xA;API call with the &lt;code&gt;USER_SRP_AUTH&lt;/code&gt; auth flow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First of all I don&amp;rsquo;t think it&amp;rsquo;s very clear what is expected to be provided in&#xA;that documentation alone, but also, take a look at &lt;a href=&#34;https://github.com/capless/warrant/blob/master/warrant/aws_srp.py&#34; target=&#34;_blank&#34;&gt;Warrant&amp;rsquo;s&#xA;implementation&lt;/a&gt;&#xA;and specifically how to generate an &lt;code&gt;SRP_A&lt;/code&gt;, which also doesn&amp;rsquo;t appear to be&#xA;explained anywhere (no where obvious at least).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it wasn&amp;rsquo;t until much later, we discovered that we could (in the case of&#xA;&lt;code&gt;InitiateAuth&lt;/code&gt; at least) have avoided writing all the SRP generation code and&#xA;instead used the &lt;em&gt;admin&lt;/em&gt; version of that API, called&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;AdminInitiateAuth&lt;/code&gt;&lt;/a&gt;&#xA;which allows you to skip SRP in favour of implicitly trusting the caller &amp;ndash;&#xA;which was fine for our use case as we were building a centralized&#xA;authentication API service.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;aws-hosted-ui&#34;&gt;AWS Hosted UI&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;AWS Cognito offers a &amp;lsquo;hosted ui&amp;rsquo;, where by you redirect a user to an endpoint&#xA;such as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;https://{...}.auth.us-east-1.amazoncognito.com/login?\&#xA;response_type={...}&amp;amp;client_id={...}&amp;amp;redirect_uri={...}&amp;amp;state={...}`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a custom domain can also be configured, but it requires you use &lt;a href=&#34;https://aws.amazon.com/certificate-manager/&#34; target=&#34;_blank&#34;&gt;AWS&#xA;Certificate Manager&lt;/a&gt; for the TLS&#xA;cert.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The hosted ui option gives you all the interactions in a fully functioning&#xA;interface, which includes: sign-in, sign-up, forgotten username, forgotten&#xA;password, social logins.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But there are some caveats:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Very limited controls over the ui (&lt;em&gt;very&lt;/em&gt; basic font colors and css).&lt;/li&gt;&#xA;&lt;li&gt;Custom domains only work with TLS certificates via &lt;a href=&#34;https://aws.amazon.com/certificate-manager/&#34; target=&#34;_blank&#34;&gt;ACM&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;State parameter overloading&lt;/li&gt;&#xA;&lt;li&gt;Can&amp;rsquo;t access new signup passwords †&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this was necessary for my use case as I needed to co-support a legacy system&#xA;that wasn&amp;rsquo;t ready to migrate over to Cognito&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;There are other issues still that I have with the hosted ui, but in a lot of&#xA;cases it does the job well enough to put up with them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;state&amp;rsquo; parameter overloading is an interesting issue and I&amp;rsquo;ll come back to&#xA;that later on when I discuss a little bit about sign-ins with social providers.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;stateless-authentication&#34;&gt;Stateless Authentication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The thing we liked about Cognito was that it would allow us to build a&#xA;&amp;lsquo;stateless&amp;rsquo; authentication system. Due to the use of &lt;a href=&#34;https://jwt.io/&#34; target=&#34;_blank&#34;&gt;JWT&lt;/a&gt;s we&#xA;could pass these tokens around (†) and know that if the user had these tokens&#xA;that they would be valid and untampered with (because when decoding the tokens&#xA;we could verifiy this using the public signing key AWS uses to sign the tokens&#xA;at point of generation).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† we only ever pass tokens around &amp;lsquo;server-side&amp;rsquo;, using secure cookies (with&#xA;HttpOnly and Secure attributes set) to avoid replay attacks that might occur&#xA;if we exposed the tokens to the client.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The problem we then stumbled across was: what happens if a user authenticates on&#xA;a public computer but doesn&amp;rsquo;t log out (or they authenticate on their laptop but&#xA;have no password to prevent someone from stealing it and thus their existing&#xA;authenticated session tokens)?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, we would still decode the ID JWT we got back from Cognito (to ensure there&#xA;was no tampering of the token), but we would then make a simple API call to AWS&#xA;(specifically the&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;GetUser&lt;/code&gt;&lt;/a&gt;)&#xA;as it required us to provide the ACCESS JWT we get back from Cognito.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I mention this is because, we needed a way to invalidate a session,&#xA;and the only way to do that was to call the&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;GlobalSignOut&lt;/code&gt;&lt;/a&gt;&#xA;API.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We originally though that would invalidate all tokens ID/Access/Refresh, but we&#xA;were wrong. Only the Access and Refresh tokens are invalidated. But that was&#xA;fine as our system was already being passed the Access token and so once we&#xA;invalidated the session, if that user tried to reuse the tokens at one of our&#xA;protected endpoints, we could be sure that it would now fail to give them access&#xA;as we not only verified the ID token but attempted to use the Access token to&#xA;call an AWS API to see if it suceeded or not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our use case is probably quite unconventional, but otherwise the whole point of&#xA;having a stateless system was in danger of being made redundant by the fact that&#xA;&lt;em&gt;if&lt;/em&gt; (for &lt;em&gt;whatever&lt;/em&gt; reason) we had a set of compromised users we&amp;rsquo;d otherwise&#xA;have no way to invalidate their sessions (and we didn&amp;rsquo;t want to have to build&#xA;our own session state datastore to track all this).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;logic-processing-with-aws-lambda&#34;&gt;Logic Processing with AWS Lambda&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With the hosted ui option you&amp;rsquo;ll likely also need to utilise &lt;a href=&#34;https://aws.amazon.com/lambda/&#34; target=&#34;_blank&#34;&gt;AWS&#xA;Lambda&lt;/a&gt; in order to do some logic processing.&#xA;The following diagram demonstrates how we were initially using the hosted ui:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/cognito-high-level.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/cognito-high-level.png&#34; alt=&#34;cognito high level&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We redirect an unauthenticated user to Cognito.&lt;/li&gt;&#xA;&lt;li&gt;Once the user attempts to sign-in we trigger some additional&#xA;&amp;lsquo;&lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html&#34; target=&#34;_blank&#34;&gt;hooks&lt;/a&gt;&amp;rsquo;.&lt;/li&gt;&#xA;&lt;li&gt;Cognito redirects the authenticated user to our API service †&lt;/li&gt;&#xA;&lt;li&gt;Our API service redirects the user back to the CMS (with user tokens).&lt;/li&gt;&#xA;&lt;li&gt;The CMS asks the API service to validate the tokens.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this service exchanges the given Cognito auth code for the user&amp;rsquo;s Cognito&#xA;User Pool tokens.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Once the tokens are validated, the CMS will allow the user to view the relevant&#xA;page.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;beware-the-lambdas&#34;&gt;Beware the Lambdas&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth noting the second half of the above diagram (the section &lt;em&gt;after&lt;/em&gt; the&#xA;lambda is triggered). What we have there are two separate lambda&amp;rsquo;s, and which&#xA;one is triggered depends on the scenario.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the user has tried to authenticate using a username/password set of&#xA;credentials, and those don&amp;rsquo;t match an existing user within the Cognito User&#xA;Pool, then the &amp;ldquo;User Migration&amp;rdquo; lambda is triggered. In that lambda we attempt&#xA;to authenticate the user within our legacy system (that is the call over to the&#xA;&amp;ldquo;WebApp&amp;rdquo; in the diagram).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the authentication with the legacy system is successful, then we&amp;rsquo;ll modify&#xA;the user&amp;rsquo;s User Pool record (which hasn&amp;rsquo;t actually been created yet) to include&#xA;auth related details we&amp;rsquo;ve pulled from their legacy account. We then return the&#xA;&amp;lsquo;event&amp;rsquo; object provided to Lambda, which let&amp;rsquo;s Cognito know it can now create&#xA;the user within its User Pool (not returning the lambda event object indicates&#xA;an error occurred and the whole request flow fails).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;with the &amp;lsquo;user migration&amp;rsquo; for users from our legacy system over to&#xA;Cognito, before we return the event in the lambda, we make sure to mark the&#xA;new Cognito user as &amp;lsquo;verified/confirmed&amp;rsquo; &amp;ndash; that way they don&amp;rsquo;t need to enter&#xA;a verification code that gets emailed or sent via SMS (that&amp;rsquo;s because the user&#xA;would&amp;rsquo;ve already verified themselves originally in our legacy system).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason I say &amp;ldquo;beware the lambdas&amp;rdquo; is because yes, code errors can cause it&#xA;to bomb out, but more importantly they don&amp;rsquo;t always fire when you think they&#xA;will (this is a user error thing, not an AWS bug).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To clarify, let me explain what we saw when testing the migration path of a&#xA;legacy user account to Cognito, when the user was signing into Cognito using&#xA;their social provider details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We had hoped the &amp;lsquo;User Migration&amp;rsquo; lambda hook would have been triggered by both&#xA;a Cognito User Pool account login and also a Social Provider account login, but&#xA;it doesn&amp;rsquo;t.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when a user signs-in with a social account, they have an account created&#xA;within the Cognito User Pool, but they are also added to a specific group&#xA;(such as a Facebook group or a Google group).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We &lt;em&gt;eventually&lt;/em&gt; discovered that the &amp;lsquo;Post Confirmation&amp;rsquo; hook would fire at the&#xA;right interval for us to do the processing we needed for users signing in with a&#xA;Social Account. But that wasn&amp;rsquo;t immediately obvious.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Before settling on the &amp;lsquo;Post Confirmation&amp;rsquo; hook, we originally started using&#xA;&amp;lsquo;Post Authentication&amp;rsquo; for handling first time social logins (the hook sounded&#xA;reasonable enough), but when we were testing this hook we already had the social&#xA;account stored in our User Pool (this was from earlier testing, before we&#xA;decided to do some &amp;lsquo;post-login&amp;rsquo; processing).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I mention this is because a week later we decided to clear out our&#xA;User Pool and start testing our various scenarios again from scratch, and we&#xA;noticed the &amp;lsquo;post authentication&amp;rsquo; hook was no longer firing 🤔&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Turns out social accounts only trigger &amp;lsquo;post migration&amp;rsquo; hooks when they already&#xA;exist in the User Pool. In order to do the &amp;lsquo;first time login&amp;rsquo; modification we&#xA;were looking for, we needed the &amp;lsquo;post confirmation&amp;rsquo; hook.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using this hook wasn&amp;rsquo;t &lt;em&gt;obvious&lt;/em&gt; to us because &amp;lsquo;post confirmation&amp;rsquo; makes it&#xA;sounds like an event that happens once a username/password user has entered&#xA;their &amp;lsquo;verification code&amp;rsquo; for the first time (and thus become marked as&#xA;&amp;lsquo;confirmed&amp;rsquo; within the User Pool). Well, turns out social provider logins are&#xA;automatically considered &lt;em&gt;confirmed&lt;/em&gt; once they authenticate for the first time&#xA;(hence why that event would trigger when we needed it to).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;useful-lambdas&#34;&gt;Useful Lambdas&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are some useful lambda&amp;rsquo;s though, for example, the &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html&#34; target=&#34;_blank&#34;&gt;Custom Message Lambda&#xA;Trigger&lt;/a&gt;&#xA;is great for intercepting the emails (or SMS) messages that are sent to your&#xA;users, and allowing you to configure them however you like.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Take a look at the following code for an example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def lambda_handler(event, context):&#xA;&#xA;    domain = &#39;https://your.domain.com&#39;&#xA;    username = event.get(&#39;userName&#39;, &#39;&#39;)&#xA;    code = event[&#39;request&#39;].get(&#39;codeParameter&#39;, &#39;&#39;)&#xA;&#xA;    print(event)&#xA;&#xA;    if event[&#39;triggerSource&#39;] == &amp;quot;CustomMessage_SignUp&amp;quot;:&#xA;        event[&#39;response&#39;][&#39;emailSubject&#39;] = &amp;quot;Validate your account&amp;quot;&#xA;        event[&#39;response&#39;][&#39;emailMessage&#39;] = &amp;quot;Hi &amp;lt;b&amp;gt;&amp;quot; + username + &amp;quot;&amp;lt;/b&amp;gt;!&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                            &amp;quot;Thank you for signing up.&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                            &amp;quot;Click &amp;lt;a href=&#39;&amp;quot; + domain + &amp;quot;confirm-account-signup-validation?&amp;quot; \&#xA;                                            &amp;quot;username=&amp;quot; + username + &amp;quot;&amp;amp;code=&amp;quot; + code + &amp;quot;&#39;&amp;gt;here&amp;lt;/a&amp;gt; &amp;quot; \&#xA;                                            &amp;quot;to validate your account.&amp;quot;&#xA;&#xA;    elif event[&#39;triggerSource&#39;] == &amp;quot;CustomMessage_ForgotPassword&amp;quot;:&#xA;        event[&#39;response&#39;][&#39;emailSubject&#39;] = &amp;quot;Reset your password&amp;quot;&#xA;        event[&#39;response&#39;][&#39;emailMessage&#39;] = &amp;quot;Hi &amp;lt;b&amp;gt;&amp;quot; + username + &amp;quot;&amp;lt;/b&amp;gt;!&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                            &amp;quot;Click &amp;lt;a href=&#39;&amp;quot; + domain + &amp;quot;confirm-password-reset?&amp;quot; \&#xA;                                            &amp;quot;identifier=&amp;quot; + username + &amp;quot;&amp;amp;code=&amp;quot; + code + &amp;quot;&#39;&amp;gt;here&amp;lt;/a&amp;gt; &amp;quot; \&#xA;                                            &amp;quot;to reset your password.&amp;quot;&#xA;&#xA;    elif event[&#39;triggerSource&#39;] == &amp;quot;CustomMessage_UpdateUserAttribute&amp;quot;:&#xA;        event[&#39;response&#39;][&#39;emailSubject&#39;] = &amp;quot;Validate your new email&amp;quot;&#xA;        event[&#39;response&#39;][&#39;emailMessage&#39;] = &amp;quot;Hi &amp;lt;b&amp;gt;&amp;quot; + username + &amp;quot;&amp;lt;/b&amp;gt;!&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                            &amp;quot;Click &amp;lt;a href=&#39;&amp;quot; + domain + &amp;quot;/confirm-email-change?&amp;quot; \&#xA;                                            &amp;quot;code=&amp;quot; + code + &amp;quot;&#39;&amp;gt;here&amp;lt;/a&amp;gt; &amp;quot; \&#xA;                                            &amp;quot;to validate your new email.&amp;quot;&#xA;&#xA;    if event[&#39;triggerSource&#39;] == &amp;quot;CustomMessage_AdminCreateUser&amp;quot;:&#xA;        user_attr = event[&#39;request&#39;].get(&#39;userAttributes&#39;, {})&#xA;        user_status = user_attr.get(&#39;cognito:user_status&#39;)&#xA;        if user_status == &#39;FORCE_CHANGE_PASSWORD&#39;:&#xA;            event[&#39;response&#39;][&#39;emailSubject&#39;] = &amp;quot;Validate your account&amp;quot;&#xA;            event[&#39;response&#39;][&#39;emailMessage&#39;] = &amp;quot;Hi &amp;lt;b&amp;gt;&amp;quot; + username + &amp;quot;&amp;lt;/b&amp;gt;!&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                                &amp;quot;You attempted to signin, but your account is &#39;unverified&#39;.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                                &amp;quot;Your temporary password is &amp;lt;b&amp;gt;&amp;quot; + code + &amp;quot;&amp;lt;/b&amp;gt;.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;quot; \&#xA;                                                &amp;quot;Click &amp;lt;a href=&#39;&amp;quot; + domain + &amp;quot;/confirm-account&#39;&amp;gt;here&amp;lt;/a&amp;gt;.&amp;quot;&#xA;&#xA;    return event&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s good about this lambda is that we&amp;rsquo;re able to improve the user&amp;rsquo;s flow a&#xA;little bit. Otherwise if we relied on AWS to generate the email/SMS we&amp;rsquo;d have to&#xA;create a separate UI that allowed (for example, when verifying an account using&#xA;a code) the user to copy paste their code into the UI and then submit that code&#xA;to our server to process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By controlling the email content ourselves we can construct an endpoint that has&#xA;the verification code as a query param and make a GET request to an endpoint&#xA;that will process that code for the user (saving them from having to manually&#xA;enter anything).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Just something to consider when using Cognito: can I use lambda triggers to&#xA;&lt;em&gt;improve&lt;/em&gt; the user flow?&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;social-logins&#34;&gt;Social Logins&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One thing that might not be clear when opting for a server-side solution is how&#xA;to handle social logins (e.g. users signing in/up using facebook or google).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It might sound a bit strange, but in order to implement social logins you&amp;rsquo;ll&#xA;need to make a call to the hosted ui endpoint (mentioned earlier):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;https://{...}.auth.us-east-1.amazoncognito.com/login?response_type={...}\&#xA;&amp;amp;client_id={...}&amp;amp;redirect_uri={...}&amp;amp;state={...}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The specific endpoint you call will be based upon those supported in Cognito&amp;rsquo;s&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html&#34; target=&#34;_blank&#34;&gt;User Pools Auth&#xA;API&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, to attempt to sign-in a user with facebook you would provide a&#xA;button that links to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;https://{...}.auth.us-east-1.amazoncognito.com/oauth2/authorize?\&#xA;response_type={...}&amp;amp;client_id={...}&amp;amp;redirect_uri={...}&amp;amp;state={...}&amp;amp;identity_provider={...}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The value we use for the &lt;code&gt;response_type&lt;/code&gt; parameter is &lt;code&gt;code&lt;/code&gt;. What this does,&#xA;once the user has authenticated with their social provider (defined by the&#xA;&lt;code&gt;identity_provider&lt;/code&gt; param), is redirect the user back to your service (specified&#xA;via the &lt;code&gt;redirect_uri&lt;/code&gt; param) and then your service is responsible for&#xA;exchanging the code for the user&amp;rsquo;s User Pool Tokens (see the following section&#xA;on &lt;a href=&#34;#jwts&#34;&gt;JWTs&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The values you can assign to &lt;code&gt;identity_provider&lt;/code&gt; are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Facebook&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Google&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;LoginWithAmazon&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you were planning on handling authentication at a very low level&#xA;(instead of an SDK), then for a User Pool login you would provide the value&#xA;&lt;code&gt;COGNITO&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;overloading-the-state-parameter&#34;&gt;Overloading the State Parameter&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;state&lt;/code&gt; param is used for&#xA;&lt;a href=&#34;https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)&#34; target=&#34;_blank&#34;&gt;CSRF&lt;/a&gt;&#xA;protection, and is the only parameter that is persisted when the user is&#xA;redirected to &lt;code&gt;redirect_uri&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A common problem for people using Cognito is that they need more than one&#xA;redirect. In my case (see the earlier &amp;lsquo;hosted ui&amp;rsquo; architecture diagram) I need&#xA;to redirect the signed-in user to an API service so we can handle the exchanging&#xA;of the AWS &amp;lsquo;code&amp;rsquo; for the Cognito User Pool tokens before needing to then&#xA;redirect the user back to our actual origin service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only way we can do this is to overload the &lt;code&gt;state&lt;/code&gt; param so it has a value&#xA;like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;state=123_redirect=https://www.example.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The value &lt;code&gt;123&lt;/code&gt; is the nonce (for CSRF) and the &lt;code&gt;_&lt;/code&gt; gives us a way to split the&#xA;query param server-side to extract the secondary redirect endpoint.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s recommended you do validation on that input (e.g. a whitelist of&#xA;accepted URIs) so hackers can&amp;rsquo;t manipulate the endpoint a user is sent to once&#xA;they&amp;rsquo;ve authenticated.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;scope&#34;&gt;Scope&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One thing I stumbled across, and which took a while to figure out, was when I&#xA;tried to call the&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html&#34; target=&#34;_blank&#34;&gt;GlobalSignOut&lt;/a&gt;&#xA;API operation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It worked fine for users authenticated against the Cognito User Pool, but not&#xA;for users authenticated via their social provider.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Turns out I needed to enable the right scope within the Cognito User Pool UI&#xA;console (within &amp;ldquo;App Integration -&amp;gt; App Client Settings&amp;rdquo;, and under &amp;ldquo;Allowed&#xA;OAuth Scopes&amp;rdquo;): &lt;code&gt;aws.cognito.signin.user.admin&lt;/code&gt; needed to be ticked.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But also, when making the request to the Auth API endpoint (e.g.&#xA;&lt;code&gt;/oauth2/authorize&lt;/code&gt;), I needed to append a &lt;code&gt;scope&lt;/code&gt; query parameter:&#xA;&lt;code&gt;&amp;amp;scope=scope=openid+aws.cognito.signin.user.admin&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html&#34; target=&#34;_blank&#34;&gt;the API&#xA;docs&lt;/a&gt;&#xA;and the &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html&#34; target=&#34;_blank&#34;&gt;UI&#xA;docs&lt;/a&gt;&#xA;for more information on the reasoning.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;jwts&#34;&gt;JWTs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you exchange the cognito &amp;lsquo;code&amp;rsquo; for a user pool &amp;lsquo;token&amp;rsquo;, you&amp;rsquo;ll actually be&#xA;returned &lt;em&gt;three&lt;/em&gt; tokens:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;ID token&lt;/li&gt;&#xA;&lt;li&gt;Access token&lt;/li&gt;&#xA;&lt;li&gt;Refresh token&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see documentation for more details on &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html&#34; target=&#34;_blank&#34;&gt;these three&#xA;tokens&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The ID token provides details about the user, and the access token indicates the&#xA;access allowed to that user&amp;rsquo;s attributes stored within the Cognito User Pool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Both the ID token and access token will expire after one hour. To use them after&#xA;that you&amp;rsquo;ll need the refresh token to refresh the access/id tokens for another&#xA;hour. The refresh token expires after 30 days.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We use the ID token for verifying the user is authenticated, and we do this by&#xA;passing the token to an internal service that verifies the token hasn&amp;rsquo;t been&#xA;manipulated by checking it against the AWS&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-identity-user-pools-using-id-and-access-tokens-in-web-api&#34; target=&#34;_blank&#34;&gt;JWK&lt;/a&gt;&#xA;that cryptographically signed the token.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The JWK is a set of keys that are the public equivalent of the private keys used&#xA;by AWS to digitally sign the tokens. We acquire these via a standard format&#xA;endpoint:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the JWK&amp;rsquo;s are rotated every 24hrs (approx), and so you need to ensure&#xA;(if you&amp;rsquo;re caching the response) your code gets a fresh copy of the JWK. You&#xA;can check this by inspecting the &lt;code&gt;Cache-Control&lt;/code&gt; header set on the JWK&#xA;response.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;api-limits&#34;&gt;API Limits&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One issue we stumbled across recently was the API limits, which meant we&#xA;couldn&amp;rsquo;t make any further API requests (and for an indeterminate amount of time)&#xA;🤔&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Seems there is a &lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html&#34; target=&#34;_blank&#34;&gt;Cognito API&#xA;limits&lt;/a&gt;&#xA;reference page, but it&amp;rsquo;s still unclear how long you have to wait before you can&#xA;start making requests again.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;logout-issues&#34;&gt;Logout Issues&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;AWS provides a&#xA;&lt;a href=&#34;https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;/logout&lt;/code&gt;&lt;/a&gt;&#xA;endpoint that when visited allows a user to clear any session tracking AWS might&#xA;have on their browser.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is different to the &amp;lsquo;signout&amp;rsquo; API functionality in that the user can call&#xA;the &lt;code&gt;/logout&lt;/code&gt; endpoint without any special tokens †&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you have to provide quite specific query params (e.g. &lt;code&gt;client_id&lt;/code&gt; and&#xA;&lt;code&gt;logout_uri&lt;/code&gt; &amp;ndash; so AWS can redirect back to a pre-configured logout page that&#xA;you host) and so it&amp;rsquo;s likely you&amp;rsquo;ll want to wrap that long and ugly URL within&#xA;an &lt;code&gt;&amp;lt;a href=&#39;&#39;&amp;gt;click to logout&amp;lt;/a&amp;gt;&lt;/code&gt; link.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This endpoint is useful because if you have a social user in your user pool, and&#xA;you delete that user (something we would do regularly while we were testing in&#xA;our stage environment), you would find that AWS is tracking your browser via&#xA;session and so if you tried to sign-up or sign-in again using that same social&#xA;user you would get an &lt;code&gt;invalid grant&lt;/code&gt; exception back from AWS (this was &lt;em&gt;super&lt;/em&gt;&#xA;confusing behaviour and took a long time to figure out).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for our use case, we would have a social user (e.g. facebook or google)&#xA;sign-in for the first time, Cognito would (once the user had authenticated with&#xA;their social provider) automatically create a social user account in our user&#xA;pool &amp;hellip;BUT we have other post-processing steps and if any of those fail we want&#xA;to delete the social user and tell the user what went wrong.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But again, we &lt;em&gt;need&lt;/em&gt; to now call the &lt;code&gt;/logout&lt;/code&gt; endpoint so if that user decides&#xA;they want to try and sign-up again they don&amp;rsquo;t get a more confusing&#xA;&lt;code&gt;invalid_grant&lt;/code&gt; error message thrown at them (and we don&amp;rsquo;t have to translate&#xA;that message into something that shouldn&amp;rsquo;t even be a concern for them in the&#xA;first place).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This brings us to the problem we have with the &lt;code&gt;/logout&lt;/code&gt; endpoint&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our intention, for when we were getting an error from an AWS API operation,&#xA;would be to catch the error, then make a request to &lt;code&gt;/logout&lt;/code&gt; and have it&#xA;redirect to a failure page we host (the redirection is a built-in feature that&#xA;AWS provides via a &lt;code&gt;logout_uri&lt;/code&gt; query param).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our &lt;code&gt;logout_uri&lt;/code&gt; value (a URL) would itself have a query param specified of&#xA;&lt;code&gt;err_msg=&amp;lt;SOME_ERROR&amp;gt;&lt;/code&gt; so that our failure page could use that param to indicate&#xA;the original error to the user. Problem was in Cognito you can only specify a&#xA;logout url that matches what&amp;rsquo;s predefined in your user pool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning if we wanted to redirect to &lt;code&gt;https://example.com/failure?err_msg=foo&lt;/code&gt;&#xA;then that&amp;rsquo;s exactly what needs to be defined in Cognito (even down to the query&#xA;param). We didn&amp;rsquo;t realise this and we only had &lt;code&gt;https://example.com/failure&lt;/code&gt;&#xA;defined as a valid &lt;code&gt;logout_uri&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To solve this issue we could have explicitly specified the &lt;code&gt;err_msg&lt;/code&gt; param but&#xA;we have lots of error types to handle and so it wasn&amp;rsquo;t practical to list each&#xA;and every variant URL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to work around the fact that we can&amp;rsquo;t specify a query param (because there&#xA;are too many value variants to be practical for us to explicitly list all of&#xA;them in the UI) we now catch the original API error and redirect the user to our&#xA;failure page with the &lt;code&gt;err_msg&lt;/code&gt; param passed so we can indicate the error back&#xA;to the user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point we still need to call the AWS &lt;code&gt;/logout&lt;/code&gt; endpoint so we can clear&#xA;any session tracking. So along with the error message we display to the user, we&#xA;also show a message to say we will redirect them automatically (via JavaScript)&#xA;back to another part of our site in N seconds time (enough time for the user to&#xA;read the error we&amp;rsquo;re displaying).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Before we redirect the user to that page we first redirect them to the AWS&#xA;&lt;code&gt;/logout&lt;/code&gt; endpoint, this time specifying our failure page as the value for the&#xA;&lt;code&gt;logout_uri&lt;/code&gt; query param but just without an &lt;code&gt;err_msg&lt;/code&gt; query param provided.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our failure page is configured with a conditional check that says &amp;ldquo;if an&#xA;&lt;code&gt;err_msg&lt;/code&gt; param is passed then show error page with the JS redirect to&#xA;&lt;code&gt;/logout&lt;/code&gt;, otherwise if no &lt;code&gt;err_msg&lt;/code&gt; provided just immediately redirect to our&#xA;&lt;code&gt;/signin&lt;/code&gt; page&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So that&amp;rsquo;s how we&amp;rsquo;re resolving this issue currently. It&amp;rsquo;s not elegant for sure&#xA;but it works.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;other-concerns&#34;&gt;Other Concerns?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth me mentioning a few other concerns we had, the first of which wasn&amp;rsquo;t&#xA;directly related to Cognito but was specific to the system we were designing,&#xA;and that was &amp;lsquo;atomic operations&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We had to make changes to Cognito and then sync some behaviours back to our&#xA;legacy system. If there was a network (or other) fault then we needed both&#xA;systems to be tolerant and to undo any data modifcations in case of failure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other than that we would be storing off the JWT tokens we received from AWS into&#xA;secure cookies (+Secure +HttpOnly attributes), and this caused us issues because&#xA;our cookies needed to be scoped to the right domains to prevent overloading the&#xA;HTTP request header limit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Due to the JWTs being large in size, and the fact that BuzzFeed has many&#xA;services/properties for users to interact with, we noticed that some users would&#xA;end up seeing a &lt;code&gt;400 Bad Request&lt;/code&gt; caused by the large cookies. The routing&#xA;services in front of these upstreams are generally nginx instances and so we&#xA;would use &lt;code&gt;large_client_header_buffers&lt;/code&gt; to allow an increased size until such a&#xA;time we could figure out an appropriate solution.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;which-is-the-right-solution&#34;&gt;Which is the right solution?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The answer: it depends.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me the server-side solution made the most sense, and although difficult in&#xA;the beginning (primarily due to documentation and general mis-understandings&#xA;about the difference between User Pools and Identity Pools) we found it worked&#xA;the best for our requirements, and gave us the most flexibility.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;updated-architecture&#34;&gt;Updated Architecture&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested the updated architecture looked something like this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/cognito-high-level-new-arch.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/cognito-high-level-new-arch.png&#34; alt=&#34;cognito high level new arch&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;None of the listed services are public, they&amp;rsquo;re all internal. The &amp;ldquo;API Gateway&amp;rdquo;&#xA;is an internal tool that allows upstreams (such as the &lt;code&gt;buzzfeed_auth_api&lt;/code&gt; to&#xA;control concurrency and rate limiting) of downstream consumers (such as&#xA;&lt;code&gt;buzzfeed_auth_ui&lt;/code&gt; and &lt;code&gt;user_settings&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we migrated certain &amp;lsquo;user settings&amp;rsquo; functionality out of our&#xA;monolithic webapp and not other user features is because we only wanted to move&#xA;behaviours that interacted with fields that needed sync&amp;rsquo;ing between Cognito and&#xA;our legacy datastore. As times goes on, we&amp;rsquo;ll start to migrate more and more&#xA;functionality out into separate services.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;native-mobile-social-sign-ins&#34;&gt;Native Mobile Social Sign-ins&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We discovered that the social sign-in for native mobile apps doesn&amp;rsquo;t work as&#xA;well as the web SDK&amp;rsquo;s. Mobile apps need to instead do things differently as&#xA;their SDK&amp;rsquo;s aren&amp;rsquo;t as &amp;lsquo;integrated&amp;rsquo; like web.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/mobile-app-authentication-flow.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/mobile-app-authentication-flow.png&#34; alt=&#34;mobile app authentication flow&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;user-pool-configuration&#34;&gt;User Pool Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As far as the User Pool is concerned you&amp;rsquo;ll need a few things:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is based on a server-side solution.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application Client&lt;/strong&gt;: this will generate a client &amp;lsquo;id&amp;rsquo; and &amp;lsquo;secret&amp;rsquo;, which&#xA;your application(s) will need to use when making certain API calls †&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Federated Identity Providers&lt;/strong&gt;: this is where you tell Cognito about your&#xA;social providers (facebook, google etc).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAM User&lt;/strong&gt;: some API calls require AWS credentials (access/secret key), so&#xA;you&amp;rsquo;ll need to create an IAM user and define the various Cognito APIs you want&#xA;it to have access to.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† even if you opt for the &amp;lsquo;hosted ui&amp;rsquo; solution, you&amp;rsquo;ll still need an&#xA;application client (for two reasons). Firstly you&amp;rsquo;ll configure which&#xA;&amp;lsquo;providers&amp;rsquo; you want your client app to support, and this will affect what the&#xA;hosted ui will display to your users. Secondly, the client app id is used as&#xA;part of the hosted ui uri; meaning you can have &lt;em&gt;different&lt;/em&gt; hosted ui&amp;rsquo;s (all&#xA;configured slightly differently).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;iam-user&#34;&gt;IAM User&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The IAM &lt;em&gt;user&lt;/em&gt; is necessary as we have to provide some credentials to the &lt;a href=&#34;https://boto3.readthedocs.io/en/latest/reference/services/cognito-idp.html&#34; target=&#34;_blank&#34;&gt;boto&#xA;client&lt;/a&gt;&#xA;(&lt;a href=&#34;https://boto3.readthedocs.io/en/latest/reference/core/boto3.html&#34; target=&#34;_blank&#34;&gt;boto&lt;/a&gt; is the&#xA;Python SDK) in order for it to make certain API calls. Below is an example of&#xA;the code to instantiate a client:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;client = boto3.client(&#39;cognito-idp&#39;, **{&#39;aws_access_key_id&#39;: access_key,&#xA;                                        &#39;aws_secret_access_key&#39;: secret_key,&#xA;                                        &#39;region_name&#39;: region})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the service name is &lt;code&gt;cognito-idp&lt;/code&gt; and not &lt;code&gt;cognito-identity&lt;/code&gt;. I mention&#xA;this as the docs specify two different services &amp;ldquo;CognitoIdentity&amp;rdquo; and&#xA;&amp;ldquo;CognitoIdentityProvider&amp;rdquo;, which when we were first learning about Cognito we&#xA;presumed the latter &amp;ldquo;CognitoIdentityProvider&amp;rdquo; was something associated with&#xA;Cognito Identity Pools.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As we were only interested in the User Pool functionality, we found it strange&#xA;that the small number of examples we found online all referenced &lt;code&gt;cognito-idp&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we struggled for a bit to understand the difference, and although we used the&#xA;&amp;ldquo;CognitoIdentityProvider&amp;rdquo; service (i.e. &lt;code&gt;cognito-idp&lt;/code&gt;), we were confused for a&#xA;long time as to why that was the case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Turns out that Cognito&amp;rsquo;s &amp;ldquo;User Pool&amp;rdquo; is itself fundamentally a &lt;em&gt;identity&#xA;provider&lt;/em&gt; (idp), and because of that you can configure a &amp;ldquo;Identity Pool&amp;rdquo; to have&#xA;a &amp;ldquo;User Pool&amp;rdquo; associated within it (along with more common external identity&#xA;providers such as Facebook and Google).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with that understanding firmly in place, the fact the SDK uses &lt;code&gt;cognito-idp&lt;/code&gt;&#xA;for interacting with a User Pool makes total sense (because the User Pool &lt;em&gt;is&lt;/em&gt;&#xA;an &amp;ldquo;idp&amp;rdquo;), and the Identity Pool is just a tool for handling &amp;ldquo;identities&amp;rdquo; via&#xA;many different providers (whether that be a User Pool or a social &amp;lsquo;provider&amp;rsquo;&#xA;such as Facebook or Google), and so the SDK using &lt;code&gt;cognito-identity&lt;/code&gt; for&#xA;interating with AWS Identity Pools also makes perfect sense.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s the little details that can really make a difference to even the simplest&#xA;aspects of using an SDK/API, and why Amazon&amp;rsquo;s atrocious documentation is a real&#xA;detriment to its users.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;lambda-iam-role&#34;&gt;Lambda IAM Role&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is an example IAM role policy you can use for AWS Lambda (if you&amp;rsquo;re using&#xA;the hosted ui option and need lambda for logic processing):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;    &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;    &amp;quot;Statement&amp;quot;: [&#xA;        {&#xA;            &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;            &amp;quot;Action&amp;quot;: [&#xA;                &amp;quot;logs:CreateLogGroup&amp;quot;,&#xA;                &amp;quot;logs:CreateLogStream&amp;quot;,&#xA;                &amp;quot;logs:PutLogEvents&amp;quot;&#xA;            ],&#xA;            &amp;quot;Resource&amp;quot;: &amp;quot;arn:aws:logs:*:*:*&amp;quot;&#xA;        },&#xA;        {&#xA;            &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;            &amp;quot;Action&amp;quot;: [&#xA;                &amp;quot;cognito-idp:AdminUpdateUserAttributes&amp;quot;&#xA;            ],&#xA;            &amp;quot;Resource&amp;quot;: &amp;quot;arn:aws:cognito-idp:us-east-1:{aws_account_id}:userpool/{user_pool_id}&amp;quot;&#xA;        }&#xA;    ]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It simply sets up CloudWatch logs access, and allows us (as an &amp;lsquo;admin&amp;rsquo;) to&#xA;update user attributes within our User Pool.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re &amp;lsquo;copying and pasting&amp;rsquo;, don&amp;rsquo;t forget to update &lt;code&gt;aws_account_id&lt;/code&gt;&#xA;and &lt;code&gt;user_pool_id&lt;/code&gt; in the code snippet.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;example-python-api-code&#34;&gt;Example Python API code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a small slice of some Python code I wrote for abstracting away the API&#xA;interactions with Cognito. Some readers might find it useful for understanding&#xA;parts of Cognito (apologies if it&amp;rsquo;s a bit ambiguous, as it&amp;rsquo;s taken out of&#xA;context).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# standard library modules&#xA;&#xA;import json&#xA;import re&#xA;from functools import reduce&#xA;from typing import Dict, List, Optional, Tuple&#xA;&#xA;# application modules&#xA;&#xA;import app.exceptions as exceptions&#xA;import app.network&#xA;import app.security&#xA;&#xA;# external modules&#xA;&#xA;from bf_auth.utility import extract_status_code, instr_exc&#xA;&#xA;import boto3&#xA;from botocore.exceptions import ClientError&#xA;&#xA;# configuration&#xA;&#xA;aws_access_key = config.get(&#39;aws_application_access_key&#39;)&#xA;aws_region = config.get(&#39;cognito_region&#39;)&#xA;aws_secret_key = config.get(&#39;aws_application_secret_key&#39;)&#xA;client_id = config.get(&#39;app_client_id&#39;)&#xA;client_secret = config.get(&#39;app_secret_key&#39;)&#xA;cognito_domain = config.get(&#39;cognito_domain&#39;)&#xA;default_redirect = config.get(&#39;default_redirect&#39;)&#xA;credentials = {&#39;aws_access_key_id&#39;: aws_access_key, &#39;aws_secret_access_key&#39;: aws_secret_key, &#39;region_name&#39;: aws_region}&#xA;sdk = boto3.client(&#39;cognito-idp&#39;, **credentials)&#xA;user_pool_id = config.get(&#39;cognito_user_pool_id&#39;)&#xA;user_pool_jwk = f&#39;https://cognito-idp.{aws_region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json&#39;&#xA;&#xA;&#xA;def attr_adapter(attributes: dict) -&amp;gt; List[Dict[str, str]]:&#xA;    &amp;quot;&amp;quot;&amp;quot;Convert dictionary into a Cognito compatible structure.&amp;quot;&amp;quot;&amp;quot;&#xA;    return [{&#39;Name&#39;: key, &#39;Value&#39;: value} for key, value in attributes.items()]&#xA;&#xA;&#xA;def create_user(username: str,&#xA;                password: str,&#xA;                verified: bool,&#xA;                email: str,&#xA;                user_info_id: str) -&amp;gt; Optional[dict]:&#xA;    &amp;quot;&amp;quot;&amp;quot;Create the user, then authenticate them to acquire their tokens.&#xA;&#xA;    If the record is created successfully, we&#39;ll return user tokens.&#xA;&#xA;    We use the &#39;Server Side Authentication Flow&#39; for authenticating and&#xA;    migrating users with Cognito (this means no need for generating an SRP)&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    # default to forcing user to validate&#xA;    message_action = {}  # type: ignore&#xA;    cognito_password = app.security.random()&#xA;    user_verified = False&#xA;&#xA;    if verified:&#xA;        message_action = {&#39;MessageAction&#39;: &#39;SUPPRESS&#39;}&#xA;        cognito_password = password&#xA;        user_verified = True&#xA;&#xA;    attributes = {&#39;email&#39;: email,&#xA;                  &#39;email_verified&#39;: str(verified).lower(),&#xA;                  &#39;custom:user_info_id&#39;: str(user_info_id)}&#xA;&#xA;    cognito_attributes = attr_adapter(attributes)&#xA;&#xA;    # we use admin_create_user so that we can choose to either suppress or&#xA;    # trigger the sending of a &#39;verify your account&#39; email.&#xA;    #&#xA;    # but in using this api call, cognito requires us to set a temporary&#xA;    # password for the user.&#xA;    #&#xA;    # so in the case of a verified user we set their password to their actual&#xA;    # password (so they notice no difference), where as with an unverified user&#xA;    # we will generate them a random password as they&#39;ll then reset that&#xA;    # password when cognito sends them the account verification email.&#xA;    try:&#xA;        sdk.admin_create_user(**{&#39;UserPoolId&#39;: user_pool_id,&#xA;                                 &#39;UserAttributes&#39;: cognito_attributes,&#xA;                                 &#39;Username&#39;: username,&#xA;                                 &#39;TemporaryPassword&#39;: cognito_password,&#xA;                                 **message_action})&#xA;&#xA;    except Exception as exc:&#xA;        msg = &#39;USER_CREATE_FAILED&#39;&#xA;        instr_exc(exc, msg,&#xA;                  metric_name=&#39;create.user&#39;,&#xA;                  context=&#39;normal&#39;,&#xA;                  scope=&#39;cognito&#39;,&#xA;                  state=&#39;failed&#39;,&#xA;                  verified=user_verified,&#xA;                  user_info_id=user_info_id)&#xA;        raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    # also for a verified user we&#39;ll try to authenticate and acquire their user&#xA;    # pool tokens, which will be returned to the caller of this function.&#xA;    if user_verified:&#xA;        auth_params = {&#39;USERNAME&#39;: username,&#xA;                       &#39;PASSWORD&#39;: password,&#xA;                       &#39;SECRET_HASH&#39;: app.security.hash(username)}&#xA;&#xA;        challenge_responses = {&#39;USERNAME&#39;: username,&#xA;                               &#39;NEW_PASSWORD&#39;: password,&#xA;                               &#39;SECRET_HASH&#39;: auth_params[&#39;SECRET_HASH&#39;]}&#xA;&#xA;        try:&#xA;            auth_response = sdk.admin_initiate_auth(UserPoolId=user_pool_id,&#xA;                                                    ClientId=client_id,&#xA;                                                    AuthFlow=&#39;ADMIN_NO_SRP_AUTH&#39;,&#xA;                                                    AuthParameters=auth_params)&#xA;&#xA;            challenge_name = auth_response.get(&#39;ChallengeName&#39;)&#xA;            session = auth_response.get(&#39;Session&#39;)&#xA;&#xA;            response = sdk.admin_respond_to_auth_challenge(UserPoolId=user_pool_id,&#xA;                                                           ClientId=client_id,&#xA;                                                           ChallengeName=challenge_name,&#xA;                                                           ChallengeResponses=challenge_responses,&#xA;                                                           Session=session)&#xA;&#xA;            result = response.get(&#39;AuthenticationResult&#39;, {})&#xA;            tokens = {&#39;id_token&#39;: result.get(&#39;IdToken&#39;),&#xA;                      &#39;access_token&#39;: result.get(&#39;AccessToken&#39;),&#xA;                      &#39;refresh_token&#39;: result.get(&#39;RefreshToken&#39;),&#xA;                      &#39;token_type&#39;: result.get(&#39;TokenType&#39;)}&#xA;&#xA;            return tokens&#xA;        except Exception as exc:&#xA;            msg = &#39;USER_AUTH_FAILED&#39;&#xA;            instr_exc(exc, msg,&#xA;                      metric_name=&#39;create.user&#39;,&#xA;                      context=&#39;normal&#39;,&#xA;                      scope=&#39;cognito&#39;,&#xA;                      state=&#39;failed&#39;,&#xA;                      verified=user_verified,&#xA;                      user_info_id=user_info_id)&#xA;            raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    # if we haven&#39;t returned some tokens already, then that means we&#xA;    # successfully created a cognito account for an unverified user, and now we&#xA;    # can raise the relevant exception that will be served back to the&#xA;    # application JS to handle (i.e. display a message to the user)&#xA;    msg = &#39;USER_MIGRATE_UNVERIFIED&#39;&#xA;    gen_exc = exceptions.CognitoException(msg, code=201)&#xA;    raise gen_exc&#xA;&#xA;&#xA;def delete_user(username) -&amp;gt; bool:&#xA;    &amp;quot;&amp;quot;&amp;quot;Delete user record associated with the given username.&#xA;&#xA;    If the record is deleted successfully, we&#39;ll return True.&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminDeleteUser.html&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    try:&#xA;        sdk.admin_delete_user(**{&#39;UserPoolId&#39;: user_pool_id,&#xA;                                 &#39;Username&#39;: username})&#xA;&#xA;    except ClientError as exc:&#xA;        error = exc.response.get(&#39;Error&#39;, {})&#xA;        error_code = error.get(&#39;Code&#39;)&#xA;&#xA;        msg = &#39;USER_DELETE_FAILED&#39;&#xA;        exc_tags = {&#39;metric_name&#39;: &#39;user.delete&#39;,&#xA;                    &#39;state&#39;: &#39;failed&#39;,&#xA;                    &#39;scope&#39;: &#39;cognito&#39;}&#xA;&#xA;        if error_code == &#39;UserNotFoundException&#39;:&#xA;            instr_exc(exc, msg, **exc_tags)&#xA;            raise exceptions.CognitoException(msg, code=404)&#xA;        else:&#xA;            instr_exc(exc, msg, **exc_tags)&#xA;            raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    except Exception as exc:&#xA;        msg = &#39;USER_DELETE_FAILED&#39;&#xA;        exc_tags = {&#39;metric_name&#39;: &#39;user.delete&#39;,&#xA;                    &#39;state&#39;: &#39;failed&#39;,&#xA;                    &#39;scope&#39;: &#39;cognito&#39;}&#xA;        instr_exc(exc, msg, **exc_tags)&#xA;        raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    return True&#xA;&#xA;&#xA;@app.network.cache&#xA;async def get_keys(endpoint=user_pool_jwk) -&amp;gt; dict:&#xA;    &amp;quot;&amp;quot;&amp;quot;Retrieve JWK (for verifying tokens).&#xA;&#xA;    If successful we return a dict consisting of the cache-control response&#xA;    header value and the actual list of JWKs.&#xA;&#xA;    If unsuccessful we return the standard dictionary error format.&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    response = await app.network.http_client.fetch(endpoint)&#xA;    cache_control = response.headers.get(&#39;Cache-Control&#39;)&#xA;&#xA;    match = re.search(r&#39;max-age=(\d+)&#39;, cache_control)&#xA;&#xA;    if not match or response.code != 200:&#xA;        msg = &#39;JWK_RESPONSE_INVALID&#39;&#xA;        gen_exc = exceptions.AsyncFetchException(msg, code=response.code)&#xA;        instr_exc(gen_exc, msg, cache_control=cache_control, scope=&#39;cognito&#39;)&#xA;        raise gen_exc&#xA;&#xA;    try:&#xA;        response_data = json.loads(response.body)&#xA;    except Exception as exc:&#xA;        msg = &#39;JSON_PARSING_FAILED&#39;&#xA;        instr_exc(exc, msg, endpoint=endpoint, body=response.body, scope=&#39;cognito&#39;)&#xA;        return {&#39;state&#39;: &#39;error&#39;,&#xA;                &#39;code&#39;: 500,&#xA;                &#39;message&#39;: msg}&#xA;&#xA;    return {&#39;state&#39;: &#39;success&#39;,&#xA;            &#39;cache_control&#39;: match.group(1),&#xA;            &#39;response_body&#39;: response_data.get(&#39;keys&#39;, [])}&#xA;&#xA;&#xA;async def get_key(kid: str) -&amp;gt; str:&#xA;    &amp;quot;&amp;quot;&amp;quot;Extract signing key from JWK (for verifying tokens).&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    response = await get_keys()&#xA;    keys = response.get(&#39;response_body&#39;)&#xA;    key = list(filter(lambda x: x.get(&#39;kid&#39;) == kid, keys))&#xA;&#xA;    if len(key) &amp;lt; 1:&#xA;        raise exceptions.NoJWK(&#39;JWK_FILTER_FAILED&#39;)&#xA;&#xA;    return key[0]&#xA;&#xA;&#xA;def global_signout(access_token) -&amp;gt; bool:&#xA;    &amp;quot;&amp;quot;&amp;quot;Sign out user from all devices.&#xA;&#xA;    If the user is signed out successfully, we&#39;ll return True.&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GlobalSignOut.html&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    try:&#xA;        sdk.global_sign_out(AccessToken=access_token)&#xA;    except Exception as exc:&#xA;        msg = &#39;USER_GLOBAL_SIGNOUT_FAILED&#39;&#xA;        instr_exc(exc, msg, metric_name=&#39;user.global_signout.failed&#39;, scope=&#39;cognito&#39;)&#xA;        raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    return True&#xA;&#xA;&#xA;def admin_signout(username) -&amp;gt; bool:&#xA;    &amp;quot;&amp;quot;&amp;quot;Sign out user from all devices as an administrator.&#xA;&#xA;    If the user is signed out successfully, we&#39;ll return True.&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUserGlobalSignOut.html&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    try:&#xA;        sdk.admin_user_global_sign_out(**{&#39;UserPoolId&#39;: user_pool_id,&#xA;                                          &#39;Username&#39;: username})&#xA;    except Exception as exc:&#xA;        msg = &#39;USER_SIGNOUT_FAILED&#39;&#xA;        instr_exc(exc, msg, metric_name=&#39;user.signout.failed&#39;, scope=&#39;cognito&#39;)&#xA;        raise exceptions.CognitoException(msg, code=extract_status_code(exc))&#xA;&#xA;    return True&#xA;&#xA;&#xA;def get_attribute(key, user_attrs) -&amp;gt; Optional[str]:&#xA;    &amp;quot;&amp;quot;&amp;quot;Recursively search user attributes for given key.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    return reduce(lambda x, y: x if x.get(&#39;Name&#39;) == key else y, user_attrs)&#xA;&#xA;&#xA;async def exchange_code_for_tokens(code, redirect_host, code_verifier=None) -&amp;gt; dict:&#xA;    &amp;quot;&amp;quot;&amp;quot;Exchange the Facebook/Google authorization code for user tokens.&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html&#xA;&#xA;    Example response:&#xA;&#xA;    {&#xA;      &amp;quot;access_token&amp;quot;:&amp;quot;123&amp;quot;,&#xA;      &amp;quot;refresh_token&amp;quot;:&amp;quot;456&amp;quot;,&#xA;      &amp;quot;id_token&amp;quot;:&amp;quot;789&amp;quot;,&#xA;      &amp;quot;token_type&amp;quot;:&amp;quot;Bearer&amp;quot;,&#xA;      &amp;quot;expires_in&amp;quot;:3600&#xA;    }&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    # Note: the `redirect_uri` field isn&#39;t used for redirecting, but for verification.&#xA;    # the value needs to match what is configured within the allowed cognito&#xA;    # callback endpoints&#xA;    data = {&#39;code&#39;: code,&#xA;            &#39;grant_type&#39;: &#39;authorization_code&#39;,&#xA;            &#39;client_id&#39;: client_id,&#xA;            &#39;redirect_uri&#39;: f&#39;{redirect_host}/auth/signin/callback&#39;}&#xA;&#xA;    if code_verifier:&#xA;        data[&#39;code_verifier&#39;] = code_verifier&#xA;&#xA;    metric_tags = {&#39;metric_tags&#39;: {&#39;scope&#39;: &#39;cognito&#39;, &#39;context&#39;: &#39;social&#39;, &#39;name&#39;: &#39;token_exchange&#39;}}&#xA;    endpoint = f&#39;{cognito_domain}/oauth2/token&#39;&#xA;    headers = {&#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;}&#xA;&#xA;    response = await app.network.fetch(endpoint, post_data=data,&#xA;                                       headers=headers,&#xA;                                       auth_username=client_id,&#xA;                                       auth_password=client_secret,&#xA;                                       **metric_tags)&#xA;&#xA;    if response.get(&#39;state&#39;) == &#39;error&#39;:&#xA;        gen_exc = exceptions.AsyncFetchException(response.get(&#39;message&#39;),&#xA;                                                 code=response.get(&#39;code&#39;))&#xA;        raise gen_exc&#xA;&#xA;    return response&#xA;&#xA;&#xA;async def resend_confirmation_code(username) -&amp;gt; bool:&#xA;    &amp;quot;&amp;quot;&amp;quot;Resend account confirmation email&#xA;&#xA;    Documentation:&#xA;    https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    try:&#xA;        sdk.resend_confirmation_code(**{&#39;ClientId&#39;: client_id,&#xA;                                        &#39;SecretHash&#39;: app.security.hash(username),&#xA;                                        &#39;Username&#39;: username})&#xA;    except Exception as exc:&#xA;        msg = &#39;CONFIRMATION_RESEND_FAILED&#39;&#xA;        instr_exc(exc, msg, metric_name=&#39;user.confirmation_resend.failed&#39;, scope=&#39;cognito&#39;)&#xA;        return False&#xA;&#xA;    return True&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;example-cognito-app-settings&#34;&gt;Example Cognito App Settings&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t meant to be an exhaustive example, but it gives you an idea of some&#xA;of the configuration you&amp;rsquo;ll need.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Callback URL(s)&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://auth-api.example.com/auth/signin/callback&#34; target=&#34;_blank&#34;&gt;https://auth-api.example.com/auth/signin/callback&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sign out URL(s)&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://auth-api.example.com/auth/signout&#34; target=&#34;_blank&#34;&gt;https://auth-api.example.com/auth/signout&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allowed OAuth Flows&lt;/strong&gt;:&lt;br&gt;&#xA;Authorization code grant&lt;br&gt;&#xA;Implicit grant&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allowed OAuth Scopes&lt;/strong&gt;:&lt;br&gt;&#xA;email&lt;br&gt;&#xA;openid&lt;br&gt;&#xA;profile&lt;br&gt;&#xA;aws.cognito.signin.user.admin&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;example-cognito-user-pool-federation-identity-providers&#34;&gt;Example Cognito User Pool &amp;ldquo;Federation: Identity Providers&amp;rdquo;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For each provider there is a &amp;ldquo;Authorize Scope&amp;rdquo; section.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facebook&lt;/strong&gt;:&lt;br&gt;&#xA;public_profile,email&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Google&lt;/strong&gt;:&lt;br&gt;&#xA;profile email openid&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;facebook-attribute-mappings&#34;&gt;Facebook Attribute Mappings&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;fb: &lt;code&gt;id&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Username&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;fb: &lt;code&gt;email&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Email&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;fb: &lt;code&gt;name&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Name&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;google-attribute-mappings&#34;&gt;Google Attribute Mappings&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;google: &lt;code&gt;email&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Email&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;google: &lt;code&gt;name&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Name&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;google: &lt;code&gt;sub&lt;/code&gt; &amp;ndash;&amp;gt; user_pool: &lt;code&gt;Username&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;example-facebook-app-configuration&#34;&gt;Example Facebook App Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://developers.facebook.com/apps&#34; target=&#34;_blank&#34;&gt;https://developers.facebook.com/apps&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;App Domains&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://your-organisation.auth.us-east-1.amazoncognito.com&#34; target=&#34;_blank&#34;&gt;https://your-organisation.auth.us-east-1.amazoncognito.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privacy Policy URL&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://www.example.com/about/privacy&#34; target=&#34;_blank&#34;&gt;https://www.example.com/about/privacy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Site URL&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&#34; target=&#34;_blank&#34;&gt;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;product-added-facebook-login&#34;&gt;Product Added: &amp;ldquo;Facebook Login&amp;rdquo;&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client OAuth Login&lt;/strong&gt;:&lt;br&gt;&#xA;Yes&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web OAuth Login&lt;/strong&gt;:&lt;br&gt;&#xA;Yes&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enforce HTTPS&lt;/strong&gt;:&lt;br&gt;&#xA;Yes&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Valid OAuth Redirect URIs&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&#34; target=&#34;_blank&#34;&gt;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&lt;/a&gt;&#xA;&lt;a href=&#34;https://auth-api.example.com/auth/signin/callback&#34; target=&#34;_blank&#34;&gt;https://auth-api.example.com/auth/signin/callback&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;example-google-app-configuration&#34;&gt;Example Google App Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://console.developers.google.com/&#34; target=&#34;_blank&#34;&gt;https://console.developers.google.com/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enabled API(s)&lt;/strong&gt;:&lt;br&gt;&#xA;Google+ API&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Credentials Type&lt;/strong&gt;:&lt;br&gt;&#xA;OAuth client ID&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application Type&lt;/strong&gt;:&lt;br&gt;&#xA;Web application&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authorized JavaScript origins&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://your-organisation.auth.us-east-1.amazoncognito.com&#34; target=&#34;_blank&#34;&gt;https://your-organisation.auth.us-east-1.amazoncognito.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authorized redirect URIs&lt;/strong&gt;:&lt;br&gt;&#xA;&lt;a href=&#34;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&#34; target=&#34;_blank&#34;&gt;https://your-organisation.auth.us-east-1.amazoncognito.com/oauth2/idpresponse&lt;/a&gt;&#xA;&lt;a href=&#34;https://auth-api.example.com/auth/signin/callback&#34; target=&#34;_blank&#34;&gt;https://auth-api.example.com/auth/signin/callback&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;terraform-example&#34;&gt;Terraform Example&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Examples for Cognito User Pools can be found here:&#xA;# https://github.com/terraform-providers/terraform-provider-aws/blob/master/examples/cognito-user-pool/main.tf&#xA;&#xA;####################################################&#xA;# main.tf&#xA;####################################################&#xA;&#xA;# TODO: split this file up into separate modules&#xA;# e.g.&#xA;#&#xA;# user_pool/&#xA;# identity_pool/&#xA;&#xA;provider &amp;quot;aws&amp;quot; {&#xA;  region = &amp;quot;${var.aws_region}&amp;quot;&#xA;&#xA;  assume_role {&#xA;    role_arn = &amp;quot;${var.aws_role_arn}&amp;quot;&#xA;  }&#xA;}&#xA;&#xA;resource &amp;quot;aws_cognito_user_pool&amp;quot; &amp;quot;pool&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_user_pool&amp;quot;&#xA;&#xA;  alias_attributes         = [&amp;quot;email&amp;quot;, &amp;quot;preferred_username&amp;quot;, &amp;quot;phone_number&amp;quot;]&#xA;  auto_verified_attributes = [&amp;quot;email&amp;quot;, &amp;quot;phone_number&amp;quot;]&#xA;&#xA;  admin_create_user_config {&#xA;    allow_admin_create_user_only = false&#xA;  }&#xA;&#xA;  # container for the AWS Lambda triggers associated with the user pool.&#xA;  # https://www.terraform.io/docs/providers/aws/r/cognito_user_pool.html#lambda-configuration&#xA;  lambda_config {&#xA;    custom_message = &amp;quot;${aws_lambda_function.custom_message_lambda.arn}&amp;quot;&#xA;  }&#xA;&#xA;  mfa_configuration = &amp;quot;OPTIONAL&amp;quot;&#xA;&#xA;  sms_configuration {&#xA;    external_id    = &amp;quot;${var.environment}_${var.name}_sns_external_id&amp;quot;&#xA;    sns_caller_arn = &amp;quot;${aws_iam_role.cognito_sns_role.arn}&amp;quot;&#xA;  }&#xA;&#xA;  password_policy {&#xA;    minimum_length    = 6&#xA;    require_lowercase = false&#xA;    require_numbers   = false&#xA;    require_symbols   = false&#xA;    require_uppercase = false&#xA;  }&#xA;&#xA;  /*&#xA;  # email was a required field, but it ended up causing issues for any social&#xA;  # users whose identity is actually their mobile number. So to avoid problems&#xA;  # authenticating those users, we no longer require an email to be provided.&#xA;  schema {&#xA;    name                     = &amp;quot;email&amp;quot;&#xA;    attribute_data_type      = &amp;quot;String&amp;quot;&#xA;    developer_only_attribute = false&#xA;    mutable                  = true&#xA;    required                 = true&#xA;&#xA;    string_attribute_constraints {&#xA;      min_length = 1&#xA;      max_length = 2048&#xA;    }&#xA;  }&#xA;  */&#xA;&#xA;  schema {&#xA;    name                     = &amp;quot;some_custom_attribute&amp;quot;&#xA;    attribute_data_type      = &amp;quot;Number&amp;quot;&#xA;    developer_only_attribute = false&#xA;    mutable                  = true&#xA;    required                 = false&#xA;&#xA;    number_attribute_constraints {&#xA;      min_value = 1&#xA;      max_value = 50000000&#xA;    }&#xA;  }&#xA;  tags {&#xA;    &amp;quot;environment&amp;quot; = &amp;quot;${var.environment}&amp;quot;&#xA;    &amp;quot;service&amp;quot;     = &amp;quot;${var.name}&amp;quot;&#xA;  }&#xA;  depends_on = [&#xA;    &amp;quot;aws_iam_role.cognito_sns_role&amp;quot;,&#xA;  ]&#xA;}&#xA;&#xA;resource &amp;quot;aws_cognito_user_pool_client&amp;quot; &amp;quot;pool_client&amp;quot; {&#xA;  # Federation &amp;gt; Identity providers&#xA;  depends_on = [&#xA;    &amp;quot;aws_cognito_identity_provider.facebook_provider&amp;quot;,&#xA;    &amp;quot;aws_cognito_identity_provider.google_provider&amp;quot;,&#xA;  ]&#xA;&#xA;  # General settings &amp;gt; App clients&#xA;  user_pool_id           = &amp;quot;${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;  name                   = &amp;quot;${var.environment}_${var.name}_user_pool_client&amp;quot;&#xA;  generate_secret        = true&#xA;  refresh_token_validity = 30&#xA;  explicit_auth_flows    = [&amp;quot;ADMIN_NO_SRP_AUTH&amp;quot;, &amp;quot;USER_PASSWORD_AUTH&amp;quot;]&#xA;&#xA;  # this flag is automatically set to true when creating the user pool using the AWS console.&#xA;  # however, when creating the user pool using Terraform, this flag needs to be set explicitly.&#xA;  allowed_oauth_flows_user_pool_client = true&#xA;&#xA;  # issue: https://github.com/terraform-providers/terraform-provider-aws/issues/4476&#xA;  read_attributes  = [&amp;quot;email&amp;quot;, &amp;quot;preferred_username&amp;quot;, &amp;quot;profile&amp;quot;, &amp;quot;custom:some_custom_attribute&amp;quot;]&#xA;  write_attributes = [&amp;quot;email&amp;quot;, &amp;quot;preferred_username&amp;quot;, &amp;quot;profile&amp;quot;, &amp;quot;custom:some_custom_attribute&amp;quot;]&#xA;&#xA;  # App integration &amp;gt; App client settings&#xA;  supported_identity_providers = [&amp;quot;COGNITO&amp;quot;, &amp;quot;Facebook&amp;quot;, &amp;quot;Google&amp;quot;]&#xA;  callback_urls                = &amp;quot;${var.callback_urls}&amp;quot;&#xA;  logout_urls                  = &amp;quot;${var.logout_urls}&amp;quot;&#xA;  allowed_oauth_flows          = [&amp;quot;code&amp;quot;]&#xA;&#xA;  allowed_oauth_scopes = [&#xA;    &amp;quot;aws.cognito.signin.user.admin&amp;quot;,&#xA;    &amp;quot;email&amp;quot;,&#xA;    &amp;quot;openid&amp;quot;,&#xA;    &amp;quot;profile&amp;quot;,&#xA;  ]&#xA;}&#xA;&#xA;# aws cert configured in certs.tf&#xA;resource &amp;quot;aws_cognito_user_pool_domain&amp;quot; &amp;quot;pool_domain&amp;quot; {&#xA;  domain          = &amp;quot;${var.domain}.${var.root_domain}&amp;quot;&#xA;  certificate_arn = &amp;quot;${aws_acm_certificate.certificate.arn}&amp;quot;&#xA;  user_pool_id    = &amp;quot;${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;}&#xA;&#xA;# bug in https://github.com/terraform-providers/terraform-provider-aws/issues/4807 that keep showing changes in plan&#xA;resource &amp;quot;aws_cognito_identity_provider&amp;quot; &amp;quot;google_provider&amp;quot; {&#xA;  user_pool_id  = &amp;quot;${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;  provider_name = &amp;quot;Google&amp;quot;&#xA;  provider_type = &amp;quot;Google&amp;quot;&#xA;&#xA;  provider_details {&#xA;    authorize_scopes = &amp;quot;profile email openid&amp;quot;&#xA;    client_id        = &amp;quot;${var.google_provider_client_id}&amp;quot;&#xA;    client_secret    = &amp;quot;${var.google_provider_client_secret}&amp;quot;&#xA;  }&#xA;&#xA;  attribute_mapping {&#xA;    username = &amp;quot;sub&amp;quot;&#xA;    email    = &amp;quot;email&amp;quot;&#xA;  }&#xA;}&#xA;&#xA;# bug in https://github.com/terraform-providers/terraform-provider-aws/issues/4807 that keep showing changes in plan&#xA;resource &amp;quot;aws_cognito_identity_provider&amp;quot; &amp;quot;facebook_provider&amp;quot; {&#xA;  user_pool_id  = &amp;quot;${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;  provider_name = &amp;quot;Facebook&amp;quot;&#xA;  provider_type = &amp;quot;Facebook&amp;quot;&#xA;&#xA;  provider_details {&#xA;    authorize_scopes = &amp;quot;public_profile,email&amp;quot;&#xA;    client_id        = &amp;quot;${var.facebook_provider_client_id}&amp;quot;&#xA;    client_secret    = &amp;quot;${var.facebook_provider_client_secret}&amp;quot;&#xA;  }&#xA;&#xA;  attribute_mapping {&#xA;    username = &amp;quot;id&amp;quot;&#xA;    email    = &amp;quot;email&amp;quot;&#xA;  }&#xA;}&#xA;&#xA;# The identity pool(s) are used by our mobile apps, and allows them to authenticate&#xA;# their users via our Cognito &#39;user pool&#39;.&#xA;#&#xA;# Note: we&#39;re not sure if we need to configure anything else in facebook/google ui&#39;s?&#xA;#       we&#39;re also not sure what `server_side_token_check` (set below) really means.&#xA;resource &amp;quot;aws_cognito_identity_pool&amp;quot; &amp;quot;apps_identity_pool&amp;quot; {&#xA;  identity_pool_name               = &amp;quot;${var.environment}_${var.name}_identity_pool&amp;quot;&#xA;  allow_unauthenticated_identities = false&#xA;&#xA;  cognito_identity_providers {&#xA;    client_id               = &amp;quot;${aws_cognito_user_pool_client.pool_client.id}&amp;quot;&#xA;    provider_name           = &amp;quot;cognito-idp.us-east-1.amazonaws.com/${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;    server_side_token_check = false&#xA;  }&#xA;&#xA;  supported_login_providers {&#xA;    &amp;quot;graph.facebook.com&amp;quot;  = &amp;quot;${var.facebook_provider_client_id}&amp;quot;&#xA;    &amp;quot;accounts.google.com&amp;quot; = &amp;quot;${var.google_provider_client_id}&amp;quot;&#xA;  }&#xA;&#xA;  depends_on = [&#xA;    &amp;quot;aws_cognito_user_pool.pool&amp;quot;,&#xA;  ]&#xA;}&#xA;&#xA;# an identity pool (used by mobile apps) requires a role to be assigned to both&#xA;# authenticated and unauthenticated access (even if the identity pool is configured&#xA;# to not allow unauthenticated access, it still requires a role to be assigned)&#xA;#&#xA;# https://www.terraform.io/docs/providers/aws/r/cognito_identity_pool_roles_attachment.html&#xA;resource &amp;quot;aws_iam_role&amp;quot; &amp;quot;apps_identity_pool_authenticated&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_identitypool_authenticated&amp;quot;&#xA;&#xA;  assume_role_policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;      &amp;quot;Principal&amp;quot;: {&#xA;        &amp;quot;Federated&amp;quot;: &amp;quot;cognito-identity.amazonaws.com&amp;quot;&#xA;      },&#xA;      &amp;quot;Action&amp;quot;: &amp;quot;sts:AssumeRoleWithWebIdentity&amp;quot;,&#xA;      &amp;quot;Condition&amp;quot;: {&#xA;        &amp;quot;StringEquals&amp;quot;: {&#xA;          &amp;quot;cognito-identity.amazonaws.com:aud&amp;quot;: &amp;quot;${aws_cognito_identity_pool.apps_identity_pool.id}&amp;quot;&#xA;        },&#xA;        &amp;quot;ForAnyValue:StringLike&amp;quot;: {&#xA;          &amp;quot;cognito-identity.amazonaws.com:amr&amp;quot;: &amp;quot;authenticated&amp;quot;&#xA;        }&#xA;      }&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_role&amp;quot; &amp;quot;apps_identity_pool_unauthenticated&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_identitypool_unauthenticated&amp;quot;&#xA;&#xA;  assume_role_policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;      &amp;quot;Principal&amp;quot;: {&#xA;        &amp;quot;AWS&amp;quot;: &amp;quot;arn:aws:iam::000000000000:root&amp;quot;&#xA;      },&#xA;      &amp;quot;Action&amp;quot;: &amp;quot;sts:AssumeRole&amp;quot;,&#xA;      &amp;quot;Condition&amp;quot;: {&#xA;        &amp;quot;Bool&amp;quot;: {&#xA;          &amp;quot;aws:MultiFactorAuthPresent&amp;quot;: &amp;quot;true&amp;quot;&#xA;        }&#xA;      }&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;# we can then attach additional policies to each identity pool role&#xA;resource &amp;quot;aws_iam_role_policy&amp;quot; &amp;quot;apps_identity_pool_authenticated&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_identitypool_authenticated_policy&amp;quot;&#xA;  role = &amp;quot;${aws_iam_role.apps_identity_pool_authenticated.id}&amp;quot;&#xA;&#xA;  policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;      &amp;quot;Action&amp;quot;: [&#xA;        &amp;quot;mobileanalytics:PutEvents&amp;quot;,&#xA;        &amp;quot;cognito-sync:*&amp;quot;,&#xA;        &amp;quot;cognito-identity:*&amp;quot;&#xA;      ],&#xA;      &amp;quot;Resource&amp;quot;: [&#xA;        &amp;quot;*&amp;quot;&#xA;      ]&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;# we don&#39;t allow unauthenticated access, so just set all actions to be denied&#xA;resource &amp;quot;aws_iam_role_policy&amp;quot; &amp;quot;apps_identity_pool_unauthenticated&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_identitypool_unauthenticated_policy&amp;quot;&#xA;  role = &amp;quot;${aws_iam_role.apps_identity_pool_unauthenticated.id}&amp;quot;&#xA;&#xA;  policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Deny&amp;quot;,&#xA;      &amp;quot;Action&amp;quot;: [&#xA;        &amp;quot;*&amp;quot;&#xA;      ],&#xA;      &amp;quot;Resource&amp;quot;: [&#xA;        &amp;quot;*&amp;quot;&#xA;      ]&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;# finally, we can attach our roles to our identity pools&#xA;resource &amp;quot;aws_cognito_identity_pool_roles_attachment&amp;quot; &amp;quot;apps_identity_pool_role_attachment&amp;quot; {&#xA;  identity_pool_id = &amp;quot;${aws_cognito_identity_pool.apps_identity_pool.id}&amp;quot;&#xA;&#xA;  roles {&#xA;    &amp;quot;authenticated&amp;quot;   = &amp;quot;${aws_iam_role.apps_identity_pool_authenticated.arn}&amp;quot;&#xA;    &amp;quot;unauthenticated&amp;quot; = &amp;quot;${aws_iam_role.apps_identity_pool_unauthenticated.arn}&amp;quot;&#xA;  }&#xA;}&#xA;&#xA;/*&#xA;We originally had this policy inlined within the the below iam role,&#xA;but then discovered it caused a cyclic reference...&#xA;&#xA;aws_cognito_user_pool -&amp;gt; aws_lambda_function -&amp;gt; aws_iam_role &amp;lt;BOOM!&amp;gt; -&amp;gt; aws_cognito_user_pool&#xA;&#xA;So to avoid that we could have made the policy not depend on that&#xA;specific user pool resource, using: &amp;quot;arn:aws:cognito-idp:*:*:*&amp;quot;&#xA;but we opted to create a separate policy, which we then attach to&#xA;the existing role, and tell the policy it can&#39;t be attached until&#xA;the user pool has been created.&#xA;*/&#xA;resource &amp;quot;aws_iam_role_policy&amp;quot; &amp;quot;cognito_lambda_policy&amp;quot; {&#xA;  depends_on = [&#xA;    &amp;quot;aws_cognito_user_pool.pool&amp;quot;,&#xA;  ]&#xA;&#xA;  name = &amp;quot;send_user_email_policy&amp;quot;&#xA;  role = &amp;quot;${aws_iam_role.iam_for_lambda.id}&amp;quot;&#xA;&#xA;  policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Action&amp;quot;: [&#xA;        &amp;quot;logs:CreateLogGroup&amp;quot;,&#xA;        &amp;quot;logs:CreateLogStream&amp;quot;,&#xA;        &amp;quot;logs:PutLogEvents&amp;quot;&#xA;      ],&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;      &amp;quot;Resource&amp;quot;: &amp;quot;arn:aws:logs:*:*:*&amp;quot;&#xA;    },&#xA;    {&#xA;      &amp;quot;Action&amp;quot;: [&#xA;        &amp;quot;cognito-idp:AdminUpdateUserAttributes&amp;quot;&#xA;      ],&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,&#xA;      &amp;quot;Resource&amp;quot;: &amp;quot;${aws_cognito_user_pool.pool.arn}&amp;quot;&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_role&amp;quot; &amp;quot;iam_for_lambda&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_sendUserEmailLambdaRole&amp;quot;&#xA;&#xA;  assume_role_policy = &amp;lt;&amp;lt;EOF&#xA;{&#xA;  &amp;quot;Version&amp;quot;: &amp;quot;2012-10-17&amp;quot;,&#xA;  &amp;quot;Statement&amp;quot;: [&#xA;    {&#xA;      &amp;quot;Action&amp;quot;: &amp;quot;sts:AssumeRole&amp;quot;,&#xA;      &amp;quot;Principal&amp;quot;: {&#xA;        &amp;quot;Service&amp;quot;: &amp;quot;lambda.amazonaws.com&amp;quot;&#xA;      },&#xA;      &amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;&#xA;    }&#xA;  ]&#xA;}&#xA;EOF&#xA;}&#xA;&#xA;data &amp;quot;archive_file&amp;quot; &amp;quot;generate_custom_message_lambda&amp;quot; {&#xA;  type        = &amp;quot;zip&amp;quot;&#xA;  source_dir  = &amp;quot;${path.module}/source/&amp;quot;&#xA;  output_path = &amp;quot;lambda.zip&amp;quot;&#xA;}&#xA;&#xA;resource &amp;quot;aws_lambda_function&amp;quot; &amp;quot;custom_message_lambda&amp;quot; {&#xA;  filename         = &amp;quot;lambda.zip&amp;quot;&#xA;  function_name    = &amp;quot;${var.environment}_${var.name}_customMessages&amp;quot;&#xA;  role             = &amp;quot;${aws_iam_role.iam_for_lambda.arn}&amp;quot;&#xA;  handler          = &amp;quot;custom_message.lambda_handler&amp;quot;&#xA;  source_code_hash = &amp;quot;${data.archive_file.generate_custom_message_lambda.output_base64sha256}&amp;quot;&#xA;  runtime          = &amp;quot;python3.6&amp;quot;&#xA;}&#xA;&#xA;# this resource allows lambda to be invoked by our user pool and tripped us up initially because&#xA;# it is automatically applied when setting up the lambda trigger in the AWS console.&#xA;# however, when creating the lambda trigger via Terraform, this needs to be set explicitly.&#xA;resource &amp;quot;aws_lambda_permission&amp;quot; &amp;quot;allow_cognito&amp;quot; {&#xA;  statement_id  = &amp;quot;AllowExecutionFromCognito&amp;quot;&#xA;  action        = &amp;quot;lambda:InvokeFunction&amp;quot;&#xA;  function_name = &amp;quot;${aws_lambda_function.custom_message_lambda.function_name}&amp;quot;&#xA;  principal     = &amp;quot;cognito-idp.amazonaws.com&amp;quot;&#xA;  source_arn    = &amp;quot;${aws_cognito_user_pool.pool.arn}&amp;quot;&#xA;}&#xA;&#xA;####################################################&#xA;# certs.tf&#xA;####################################################&#xA;&#xA;resource &amp;quot;aws_acm_certificate&amp;quot; &amp;quot;certificate&amp;quot; {&#xA;  domain_name       = &amp;quot;${var.domain}.${var.root_domain}&amp;quot;&#xA;  validation_method = &amp;quot;DNS&amp;quot;&#xA;&#xA;  tags {&#xA;    &amp;quot;environment&amp;quot; = &amp;quot;${var.environment}&amp;quot;&#xA;    &amp;quot;service&amp;quot;     = &amp;quot;${var.name}&amp;quot;&#xA;  }&#xA;}&#xA;&#xA;####################################################&#xA;# outputs.tf&#xA;####################################################&#xA;&#xA;output &amp;quot;user_pool_id&amp;quot; {&#xA;  value = &amp;quot;${aws_cognito_user_pool.pool.id}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;user_pool_arn&amp;quot; {&#xA;  value = &amp;quot;${aws_cognito_user_pool.pool.arn}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;user_pool_client_id&amp;quot; {&#xA;  value = &amp;quot;${aws_cognito_user_pool_client.pool_client.id}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;user_pool_client_secret&amp;quot; {&#xA;  // this is only shown at creation&#xA;  value = &amp;quot;${aws_cognito_user_pool_client.pool_client.client_secret}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;app_user_name&amp;quot; {&#xA;  value = &amp;quot;${aws_iam_user.cognito_app_user.name}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;app_user_arn&amp;quot; {&#xA;  value = &amp;quot;${aws_iam_user.cognito_app_user.arn}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;acm_certificate_arn&amp;quot; {&#xA;  value = &amp;quot;${aws_acm_certificate.certificate.arn}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;acm_certificate_domain_name&amp;quot; {&#xA;  value = &amp;quot;${aws_acm_certificate.certificate.domain_name}&amp;quot;&#xA;}&#xA;&#xA;output &amp;quot;acm_certificate_domain_validation_options&amp;quot; {&#xA;  value = &amp;quot;${aws_acm_certificate.certificate.domain_validation_options}&amp;quot;&#xA;}&#xA;&#xA;####################################################&#xA;# required.tf&#xA;####################################################&#xA;&#xA;terraform {&#xA;  # No value within the terraform block can use interpolations. &#xA;  # The terraform block is loaded very early in the execution of Terraform and interpolations are not yet available.&#xA;  required_version = &amp;quot;0.10.7&amp;quot;&#xA;}&#xA;&#xA;####################################################&#xA;# service_iam.tf&#xA;####################################################&#xA;&#xA;resource &amp;quot;aws_iam_group&amp;quot; &amp;quot;cognito_app_group&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_group&amp;quot;&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_user&amp;quot; &amp;quot;cognito_app_user&amp;quot; {&#xA;  name = &amp;quot;${var.environment}_${var.name}_user&amp;quot;&#xA;}&#xA;&#xA;# note:&#xA;# we don&#39;t also create an &#39;aws_iam_access_key&#39; resource&#xA;# because we don&#39;t want the access key to be committed&#xA;# &#xA;# so we manually create access/secret keys via the console&#xA;&#xA;resource &amp;quot;aws_iam_user_group_membership&amp;quot; &amp;quot;cognito_app_user_groups&amp;quot; {&#xA;  user = &amp;quot;${aws_iam_user.cognito_app_user.name}&amp;quot;&#xA;&#xA;  groups = [&#xA;    &amp;quot;${aws_iam_group.cognito_app_group.name}&amp;quot;,&#xA;  ]&#xA;}&#xA;&#xA;data &amp;quot;aws_iam_policy_document&amp;quot; &amp;quot;cognito_app_group_policy&amp;quot; {&#xA;  statement {&#xA;    actions = [&#xA;      &amp;quot;cognito-idp:ListUserPools&amp;quot;,&#xA;      &amp;quot;cognito-idp:ListUsers&amp;quot;,&#xA;    ]&#xA;&#xA;    resources = [&#xA;      &amp;quot;*&amp;quot;,&#xA;    ]&#xA;  }&#xA;&#xA;  statement {&#xA;    actions = [&#xA;      &amp;quot;cognito-idp:AdminAddUserToGroup&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminConfirmSignUp&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminCreateUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminDeleteUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminDeleteUserAttributes&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminDisableProviderForUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminDisableUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminEnableUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminForgetDevice&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminGetDevice&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminGetUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminInitiateAuth&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminLinkProviderForUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminListDevices&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminListGroupsForUser&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminListUserAuthEvents&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminRemoveUserFromGroup&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminResetUserPassword&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminRespondToAuthChallenge&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminSetUserMFAPreference&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminSetUserSettings&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminUpdateAuthEventFeedback&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminUpdateDeviceStatus&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminUpdateUserAttributes&amp;quot;,&#xA;      &amp;quot;cognito-idp:AdminUserGlobalSignOut&amp;quot;,&#xA;    ]&#xA;&#xA;    resources = [&#xA;      &amp;quot;${aws_cognito_user_pool.pool.arn}&amp;quot;,&#xA;    ]&#xA;  }&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_policy&amp;quot; &amp;quot;cognito_app_group_policy&amp;quot; {&#xA;  name   = &amp;quot;${var.environment}_${var.name}_group_policy&amp;quot;&#xA;  policy = &amp;quot;${data.aws_iam_policy_document.cognito_app_group_policy.json}&amp;quot;&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_group_policy_attachment&amp;quot; &amp;quot;cognito_app_group_attachment&amp;quot; {&#xA;  group      = &amp;quot;${aws_iam_group.cognito_app_group.name}&amp;quot;&#xA;  policy_arn = &amp;quot;${aws_iam_policy.cognito_app_group_policy.arn}&amp;quot;&#xA;}&#xA;&#xA;####################################################&#xA;# sns_iam.tf&#xA;####################################################&#xA;&#xA;data &amp;quot;aws_iam_policy_document&amp;quot; &amp;quot;cognito_sns_assume_role_policy&amp;quot; {&#xA;  statement {&#xA;    actions = [&amp;quot;sts:AssumeRole&amp;quot;]&#xA;&#xA;    principals {&#xA;      type        = &amp;quot;Service&amp;quot;&#xA;      identifiers = [&amp;quot;cognito-idp.amazonaws.com&amp;quot;]&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_role&amp;quot; &amp;quot;cognito_sns_role&amp;quot; {&#xA;  name               = &amp;quot;${var.environment}_${var.name}_cognito_sns_role&amp;quot;&#xA;  assume_role_policy = &amp;quot;${data.aws_iam_policy_document.cognito_sns_assume_role_policy.json}&amp;quot;&#xA;}&#xA;&#xA;data &amp;quot;aws_iam_policy_document&amp;quot; &amp;quot;cognito_sns_publish_policy&amp;quot; {&#xA;  statement {&#xA;    actions = [&#xA;      &amp;quot;sns:Publish&amp;quot;,&#xA;    ]&#xA;&#xA;    resources = [&#xA;      &amp;quot;*&amp;quot;,&#xA;    ]&#xA;  }&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_policy&amp;quot; &amp;quot;cognito_sns_role_policy&amp;quot; {&#xA;  name   = &amp;quot;${var.environment}_${var.name}_cognito_sns_role_policy&amp;quot;&#xA;  policy = &amp;quot;${data.aws_iam_policy_document.cognito_sns_publish_policy.json}&amp;quot;&#xA;}&#xA;&#xA;resource &amp;quot;aws_iam_role_policy_attachment&amp;quot; &amp;quot;cognito_sns_role_policy_attachment&amp;quot; {&#xA;  role       = &amp;quot;${aws_iam_role.cognito_sns_role.name}&amp;quot;&#xA;  policy_arn = &amp;quot;${aws_iam_policy.cognito_sns_role_policy.arn}&amp;quot;&#xA;}&#xA;&#xA;####################################################&#xA;# vars.tf&#xA;####################################################&#xA;&#xA;variable &amp;quot;aws_role_arn&amp;quot; {}&#xA;&#xA;variable &amp;quot;aws_region&amp;quot; {&#xA;  default = &amp;quot;us-east-1&amp;quot;&#xA;}&#xA;&#xA;variable &amp;quot;environment&amp;quot; {}&#xA;&#xA;variable &amp;quot;name&amp;quot; {&#xA;  default = &amp;quot;your_service_name&amp;quot;&#xA;}&#xA;&#xA;variable &amp;quot;callback_urls&amp;quot; {&#xA;  type = &amp;quot;list&amp;quot;&#xA;}&#xA;&#xA;variable &amp;quot;logout_urls&amp;quot; {&#xA;  type = &amp;quot;list&amp;quot;&#xA;}&#xA;&#xA;variable &amp;quot;domain&amp;quot; {}&#xA;&#xA;variable &amp;quot;google_provider_client_id&amp;quot; {}&#xA;variable &amp;quot;google_provider_client_secret&amp;quot; {}&#xA;&#xA;variable &amp;quot;facebook_provider_client_id&amp;quot; {}&#xA;variable &amp;quot;facebook_provider_client_secret&amp;quot; {}&#xA;&#xA;variable &amp;quot;root_domain&amp;quot; {&#xA;  description = &amp;quot;certificate root domain&amp;quot;&#xA;  default     = &amp;quot;your-example-domain.com&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s so much more to the story, but I think this post is long enough as it is&#xA;and I don&amp;rsquo;t want to keep you any longer. If you have any questions, then please&#xA;reach out to me on twitter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I personally found the documentation around Cognito (and the various tools) to&#xA;be both overwhelming and underwhelming. Not to mention confusing in places, as&#xA;well as just downright frustrating at times.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hopefully you found this short break down of AWS Cognito useful. There&amp;rsquo;s so much&#xA;more still to dive into, but this should give you at least a decent starting&#xA;point.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/authentication-with-aws-cognito/</guid>
      <link>https://www.integralist.co.uk/posts/authentication-with-aws-cognito/</link>
      <pubDate>Fri, 15 Jun 2018 00:00:00 +0000</pubDate>
      <title>Authentication with AWS Cognito</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;what-is-a-1-1&#34;&gt;What is a 1:1 ?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A 1:1 (&amp;ldquo;one to one&amp;rdquo;) is a meeting between a manager and a &amp;lsquo;report&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-a-report&#34;&gt;What is a &amp;lsquo;report&amp;rsquo; ?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &amp;lsquo;report&amp;rsquo; is a member of staff of which the manager is responsible for. Specifically the manager is responsible for that person&amp;rsquo;s happiness at the company and their career progression.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-important-is-a-1-1&#34;&gt;How important is a 1:1 ?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A manager&amp;rsquo;s 1:1 meetings are their most important meeting, as the primary goal of this meeting is for the manager and the report to build a strong and trusted relationship.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re a line manager, then you should &lt;em&gt;always&lt;/em&gt; attend these meetings. Never skip or reschedule a 1:1 as that has the potential to give a bad impression upon your report (e.g. your report feels like they&amp;rsquo;re unimportant and not appreciated by the organisation).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As a manager, your most important priority is your staff.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-long-should-a-1-1-be&#34;&gt;How long should a 1:1 be?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At least thirty minutes, no less as there just isn&amp;rsquo;t enough time to really get into what&amp;rsquo;s on someones mind. If you schedule a fifteen minute 1:1, then this again suggests you don&amp;rsquo;t have time, or care enough, to fit your direct report into your schedule.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;when-should-1-1-meetings-happen&#34;&gt;When should 1:1 meetings happen?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;1:1&amp;rsquo;s should happen regularly. Typically they are scheduled once a week, although fortnightly (i.e. once every two weeks) is more practical for some people. Just remember that if you have them weekly, then that helps to keep them shorter in length (increase the length of the 1:1 depending on how far apart they&amp;rsquo;re scheduled).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;unless you&amp;rsquo;re an experienced engineer of many years, don&amp;rsquo;t fall into the trap of thinking &amp;ldquo;I don&amp;rsquo;t &lt;em&gt;need&lt;/em&gt; regular 1:1&amp;rsquo;s&amp;rdquo;. You&amp;rsquo;ll be surprised to discover what tidbits of feedback and shared experience can help you progress with both your practical and soft skills.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;what-do-we-talk-about-in-a-1-1-meeting&#34;&gt;What do we talk about in a 1:1 meeting?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you&amp;rsquo;re the report&lt;/strong&gt;, then quite literally &lt;em&gt;anything&lt;/em&gt; that is on your mind.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Got an issue with someone at work? Talk about it!&lt;/li&gt;&#xA;&lt;li&gt;Got problems at home with a new born baby? Talk about it!&lt;/li&gt;&#xA;&lt;li&gt;Got ideas for ways to improve company communication? Talk about it!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Remember, what you talk about doesn&amp;rsquo;t always have to be centered around work. If you&amp;rsquo;re having trouble sleeping (whether that&amp;rsquo;s because you have a new born baby or you&amp;rsquo;ve hurt your back from being sat in an office chair all day), then talk about it!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason being is that your line manager can help expedite any tasks that help to resolve these problems. Whether it be chatting with HR and Facilitaties to get you a standing desk or a new chair to help your back, or whether they can talk to the tech lead on your team to allow you some leeway as far as the tasks you&amp;rsquo;re expected to work on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe you&amp;rsquo;re interested in taking on some extra responsibilities yourself and want to do some mentoring or looking after an intern? Your line manager can help investigate all these possibilities on your behalf. They are quite literally there to help you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These meetings should be a safe space for you to share how you&amp;rsquo;re feeling, and that&amp;rsquo;s important because if you&amp;rsquo;re not feeling great (for whatever reason, whether it be physical or emotional issues), then that&amp;rsquo;s ultimately going to have an affect on your performance.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you&amp;rsquo;re a line manager&lt;/strong&gt;, then a 1:1 is your opportunity to perform weekly &amp;lsquo;preventive maintenance&amp;rsquo; and to understand the overall health of your team. If you&amp;rsquo;re effective in these meetings, then you (and the company) will be rewarded with good work from your teams and you won&amp;rsquo;t have any sudden built-up frustrations turning into drama or someone resigning.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unfortunately most 1:1&amp;rsquo;s end up being some form of status (or project) update, which isn&amp;rsquo;t good because the focus of a 1:1 is for a report to communicate with their line manager about how &lt;em&gt;their&lt;/em&gt; doing and not how the project is going †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† that&amp;rsquo;s what project/product managers are for.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;what-about-the-silent-types&#34;&gt;What about the silent types?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now not everyone is going to be overly talkative, and so it&amp;rsquo;s the line manager&amp;rsquo;s responsibility to tease out the conversation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The most common question a line manager will (or should) ask is:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;&amp;ldquo;How Are You?&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if the response is a nonchalant &amp;ldquo;Not bad&amp;rdquo;, then the line manager might have to resort to some other options for kick starting a meaningful conversation. Some examples could be:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Mini performance review&lt;/li&gt;&#xA;&lt;li&gt;A current disaster&lt;/li&gt;&#xA;&lt;li&gt;How to improve X&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Remember, we don&amp;rsquo;t want the 1:1 to be a status/project update.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;suggestions&#34;&gt;Suggestions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you are the report&lt;/strong&gt;, and you have nothing to say or have zero issues with any thing happening in the company (which to me would be doubtful), then just be aware that the meeting (if not handled properly) could turn into a status update and that&amp;rsquo;s ultimately a pointless use of everyones time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So try and make an effort to care about what&amp;rsquo;s going on in the organisation, as there is usually always &lt;em&gt;something&lt;/em&gt; that can be discussed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you are the line manager&lt;/strong&gt;, then use the above three points to help guide the conversation to a meaningful topic that benefits both yourself and your direct report.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A mini performance review is great because we should always be looking at keeping staff on track with their goals. In order to do this we need to understand their motivations and what they want from life, so start the discussion there and that will help you to understand how you can guide their progress.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Discussing a current disaster is a good way to get some feedback on a topic that&amp;rsquo;s important to the company and allows you to get the perspective of someone either not involved in the problem space or who doesn&amp;rsquo;t even work in the same area of the business. This equally allows the direct report to feel included and that their opinions matter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, choosing an area of the business where you feel could use some improvement is also a good option for opening up the discussion and having a meaningful 1:1, and it results in similar benefits as mentioned in the previous comment.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;meeting-structure&#34;&gt;Meeting structure&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the approach I&amp;rsquo;m currently taking in my 1:1 meetings&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How&amp;rsquo;s things? (in general)&lt;/li&gt;&#xA;&lt;li&gt;Any wins this past week? (positivity boost!)&lt;/li&gt;&#xA;&lt;li&gt;Any updates from last week?&lt;/li&gt;&#xA;&lt;li&gt;Any team or project concerns? (can I unblock?)&lt;/li&gt;&#xA;&lt;li&gt;Any projects you&amp;rsquo;re interested in helping with?&lt;/li&gt;&#xA;&lt;li&gt;Any broader company wide updates I can share?&lt;/li&gt;&#xA;&lt;li&gt;Any career progression updates? (either from me or the report)&lt;/li&gt;&#xA;&lt;li&gt;Any feedback on my performance so far? (make me more effective)&lt;/li&gt;&#xA;&lt;li&gt;Anything you looking forward to? (can be work related or personal)&lt;/li&gt;&#xA;&lt;li&gt;Finish by celebrating their hard work ❤️(another positivity boost)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This structure can change depending on what I know going into the meeting, as well as what arises from discussions within the meeting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Generally I want to be sure to take advantage of any opportunity where I can help a report to learn from mistakes and to share my own experiences as a way of expressing how I believe certain interactions/incidents could have been improved. Especially when it comes to &amp;lsquo;soft skills&amp;rsquo; and communication.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I also like to understand what a person&amp;rsquo;s strong points are because this person might be able to have some greater impact on a project or team that they otherwise might not realize was an opportunity for them to be a part of. I can help them progress by getting them onto projects they wouldn&amp;rsquo;t normally consider or even know about, or start helping them to prepare and to learn new relevant skills.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;making-it-personal&#34;&gt;Making it personal&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I like to find a common interest with my report. This normally happens organically but at the very least I like to have a basic understanding of what my report enjoys doing (i.e. I take an interest in them), and once I do that I feel more of a connection and more invested in helping them succeed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Do they like to read books in their spare time? Do they like rock climbing? etc. This helps me to keep the conversation light and informal when the meeting starts and I ask &amp;ldquo;How&amp;rsquo;s things with you?&amp;rdquo;, because if I don&amp;rsquo;t get much output (e.g. I&amp;rsquo;m dealing with a &amp;lsquo;quiet&amp;rsquo; one), then I feel like I can tease out some light conversation by asking about their interests.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;generality-can-be-misleading&#34;&gt;Generality can be misleading&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you ask &amp;ldquo;how are things?&amp;rdquo; you&amp;rsquo;ve asked a very general question, and that can sometimes be ok but it can also be too vague a question for your report to answer in a meaningful way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to tackle this I like to ask specific questions such as: &amp;ldquo;ok, what happened in the past week that was&amp;hellip;&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Exciting&lt;/li&gt;&#xA;&lt;li&gt;Frustrating&lt;/li&gt;&#xA;&lt;li&gt;Rewarding&lt;/li&gt;&#xA;&lt;li&gt;Challenging&lt;/li&gt;&#xA;&lt;li&gt;Engaging&lt;/li&gt;&#xA;&lt;li&gt;Boring&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice I flip-flop between positive and negative toned queries&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This helps me to tease out characteristics of the report and this helps me to then align their interests with what&amp;rsquo;s potentially happening within the organization.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understanding&#34;&gt;Understanding&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following questions are useful for getting a clearer understanding of what will and not work with your report. Remember, like how a good teacher will adapt their lesson plan for different types of students (some students have different learning styles), you should adapt your 1:1 to best fit your report (yes this takes effort, but this is your responsibility, and an important one at that).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most of these questions are taken verbatim from &lt;a href=&#34;https://twitter.com/skamille&#34; target=&#34;_blank&#34;&gt;Camille Fournier&lt;/a&gt;&amp;rsquo;s awesome book &amp;ldquo;&lt;a href=&#34;http://shop.oreilly.com/product/0636920056843.do&#34; target=&#34;_blank&#34;&gt;The Manager&amp;rsquo;s Path&lt;/a&gt;&amp;rdquo; and is strongly recommended reading!&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How do you like to be praised, in public or in private?&lt;/li&gt;&#xA;&lt;li&gt;What is your preferred method of communication for serious feedback? Do you prefer to get such feedback in writing so you have time to digest it, or are you comfortable with less formal verbal feedback?&lt;/li&gt;&#xA;&lt;li&gt;Why did you decide to work here?&lt;/li&gt;&#xA;&lt;li&gt;What are you excited about working here?&lt;/li&gt;&#xA;&lt;li&gt;How do I know when you&amp;rsquo;re in a bad mood or annoyed? Are there things that always put you in a bad mood that I should be aware of? (e.g. does your report fast for a religious holiday which can make them a bit grumpy)&lt;/li&gt;&#xA;&lt;li&gt;Are there any manager behaviours you hate?&lt;/li&gt;&#xA;&lt;li&gt;Do you have any clear career goals that I should know about so I can help you achieve them?&lt;/li&gt;&#xA;&lt;li&gt;Any surprises since you joined, good or bad, that I should know about? (e.g. where are my stock options? you promised me a relocation bonus and I&amp;rsquo;ve not received it)&lt;/li&gt;&#xA;&lt;li&gt;Would you like more or less direction from me on your work?&lt;/li&gt;&#xA;&lt;li&gt;What could I do to make you enjoy your work more?&lt;/li&gt;&#xA;&lt;li&gt;What part of the day do you have the most energy and focus? What changes could we make to accommodate this?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;soliciting-ideas&#34;&gt;Soliciting Ideas&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some questions can help the report feel like their voice is heard and that their opinions matter:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How could we change our team meetings to be more effective?&lt;/li&gt;&#xA;&lt;li&gt;Do you feel your ideas are heard by the team and I?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;evolve-your-process&#34;&gt;Evolve your process&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You try things. They fail. Tweak them as necessary. If my earlier suggestions aren&amp;rsquo;t working for you, then obviously make sure you&amp;rsquo;re comfortable with them and that you feel like you&amp;rsquo;ve given them your best effort, but if they&amp;rsquo;re not working don&amp;rsquo;t keep forging ahead. Try a different approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember, these meetings aren&amp;rsquo;t about you and your success as a manager. They are about your report and &lt;em&gt;their&lt;/em&gt; success. Drop the ego and start thinking about the best interests of your reports and how you can leverage their best self to make the company as a whole better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I&amp;rsquo;m taking over reporting duties from another manager, I like to talk to the previous manager to understand what worked or didn&amp;rsquo;t work (in their opinion) when they had 1-1&amp;rsquo;s with this report. I might ignore their suggestions or I might not, but it&amp;rsquo;s good to dig into the previous manager&amp;rsquo;s experience with the report.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;track-progress&#34;&gt;Track progress&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some managers like to jot down details of their reports alongside their normal work notes. If that works for you, then fine but I personally feel that you should work with a medium that allows your notes and thoughts to be easily shareable with your report.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can continue to write private thoughts separately of course, but having a document that&amp;rsquo;s shared with the report so they can see how they&amp;rsquo;re progressing and have a place to review previous conversations is a good way for them to feel these regular conversations are providing value.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this will also be useful to you (either as a line manager or as a report) when it comes time to give/receive six monthly performance reviews, as you&amp;rsquo;ll have a complete track record of all discussions.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important for reports to understand that they own their career progression, and so once you&amp;rsquo;ve had an opportunity to understand your report the next step is for the report to come up with their goals and to pro-actively work through the relevant steps that lead to the realization of those goals.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As a manager, it&amp;rsquo;s your responsibility to help and support the report with this process.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dealing-with-issues&#34;&gt;Dealing with issues&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re a line manager, then there are two types of issues:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Mild&lt;/li&gt;&#xA;&lt;li&gt;Serious&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The first is someone just venting frustrations, the second is where they&amp;rsquo;ve reached their limits and have exploded their anger all over you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In both cases you should:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Say nothing (for now).&lt;/li&gt;&#xA;&lt;li&gt;Listen.&lt;/li&gt;&#xA;&lt;li&gt;Do not attempt to problem solve (yet).&lt;/li&gt;&#xA;&lt;li&gt;Do not comfort or try to take away their experience.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Once they have had an opportunity to say what they need to, then you can start to identify the various moving pieces of the problem (although, if they&amp;rsquo;re that angry you may find them repeating themselves and so at some point you might have to interject).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This could include discussing with them topics such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What the next steps are (e.g. intermediary and long term resolutions).&lt;/li&gt;&#xA;&lt;li&gt;How we can reach each each step as quickly and efficiently as possible.&lt;/li&gt;&#xA;&lt;li&gt;How we might prevent this issue from happening again.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re the direct report and you&amp;rsquo;re struggling with an issue to the point where you&amp;rsquo;re now very angry, then this is a good example of why it&amp;rsquo;s important to have frequent, qualitative and effective 1:1&amp;rsquo;s. They allow a lot of issues to be caught ahead of time.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;thought-leaders&#34;&gt;Thought leaders&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For anyone interested in learning more I would highly recommend following &lt;a href=&#34;https://twitter.com/integralist/lists/leads/members&#34; target=&#34;_blank&#34;&gt;these key players&lt;/a&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/pattymccord1&#34; target=&#34;_blank&#34;&gt;Patty McCord&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/aprilwensel&#34; target=&#34;_blank&#34;&gt;April Wensel&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/fredkofman&#34; target=&#34;_blank&#34;&gt;Fred Kofman&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/skamille&#34; target=&#34;_blank&#34;&gt;Camille Fournier&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/kimballscott&#34; target=&#34;_blank&#34;&gt;Kim Scott&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://twitter.com/lara_hogan&#34; target=&#34;_blank&#34;&gt;Lara Hogan&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Hopefully you&amp;rsquo;ve found this breakdown of 1:1 meetings interesting and are able to bring some new learnings into your own 1:1&amp;rsquo;s to make them more effective and successful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Good luck out there!&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/a-guide-to-effective-1-1-meetings/</guid>
      <link>https://www.integralist.co.uk/posts/a-guide-to-effective-1-1-meetings/</link>
      <pubDate>Mon, 04 Jun 2018 00:00:00 +0000</pubDate>
      <title>A Guide to Effective 1:1 Meetings</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;💡 Related information: &lt;a href=&#34;https://gist.github.com/Integralist/bfcad74c66dfa1e8eb5e2c07b13811df&#34; target=&#34;_blank&#34;&gt;Project Planning&lt;/a&gt;.&lt;br&gt;&#xA;Includes specific documents needed and also an &lt;a href=&#34;https://docs.google.com/spreadsheets/d/1ZnxIY4BCnsUaY65Cc2GCmzmq18XBJvG2iErSWfMjW10/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;example matrix&#xA;spreadsheet&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re a technical lead (aka engineering lead, lead developer, etc), then there comes a time where you&amp;rsquo;ll be put in charge of a project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may also already be quite familiar with the process (read: red tape) of certain types of project management: agile, scrum, lean etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what do you do, follow one of those methodologies to the letter and have to suffer all the process that comes along with it? You could do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me, I find the following things are good enough to get you by without having to worry about whether you&amp;rsquo;re &amp;ldquo;doing scrum&amp;rdquo; (or whatever) correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I suggest you take what you want and leave the rest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But first, let&amp;rsquo;s take a moment to recognise and understand a few distinct roles that otherwise can appear to have a lot of cross-over responsibilities (this has been summarised from the great work originally published by &lt;a href=&#34;https://medium.com/@lara.hogan&#34; target=&#34;_blank&#34;&gt;Lara Hogan&lt;/a&gt; - I highly recommend you check out her work).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-who-how-why&#34;&gt;What Who How Why?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Product Manager&lt;/strong&gt;: owns the story of &amp;ldquo;what&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Engineering Manager&lt;/strong&gt;: owns the story of &amp;ldquo;who&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Engineering Lead (Tech Lead)&lt;/strong&gt;: owns the story of &amp;ldquo;how&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;All Three&lt;/strong&gt;: each person shares ownership of the story of &amp;ldquo;why&amp;rdquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/team-leader-venn-diagram.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/team-leader-venn-diagram.png&#34; alt=&#34;team leader venn diagram&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://medium.com/making-meetup/em-el-pm-venn-diagram-764e79b42baf&#34; target=&#34;_blank&#34;&gt;More details&amp;hellip;&lt;/a&gt; (Lara Hogan&amp;rsquo;s original post)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;project-management-checklist&#34;&gt;Project Management Checklist&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a short checklist of things you probably should be doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;understand-the-requirements-and-specifically-why-they-are-important&#34;&gt;🤔 Understand the requirements, and specifically why they are important.&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you don&amp;rsquo;t understand the project values, then you&amp;rsquo;ll have a hard time building something that benefits your users.&lt;/li&gt;&#xA;&lt;li&gt;Does the project even &lt;em&gt;align&lt;/em&gt; with your team&amp;rsquo;s mission statement/responsibilities? You should be focused on building things that bring value to your stakeholders.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;create-simple-high-level-gherkin-user-stories-user-stories&#34;&gt;📝 Create simple/high-level Gherkin &lt;a href=&#34;#user-stories&#34;&gt;user stories&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This is one way of helping you better understand the product values and standards (there are other ways, but this is what I like using).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;break-down-the-requirements&#34;&gt;✅ Break down the requirements&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Define milestones and manageable sub tasks.&lt;/li&gt;&#xA;&lt;li&gt;inc. investigation time, QA (Quality Assurance) and security testing.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;prioritise-tasks&#34;&gt;🔝 Prioritise tasks&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You can do this either by &amp;lsquo;importance/impact&amp;rsquo; (High, Medium, Low) or using &amp;lsquo;MSC&amp;rsquo; (Must Should Could).&lt;/li&gt;&#xA;&lt;li&gt;Once categorized, group related items (e.g. group together all high, medium, low items).&lt;/li&gt;&#xA;&lt;li&gt;A table matrix can help visualise the various tasks and their importance.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Regardless of the approach you choose, you wont be able to prioritize using just a &amp;lsquo;problem/solution/impact&amp;rsquo; approach. You&amp;rsquo;ll need to document and consider both &amp;lsquo;cost&amp;rsquo; and &amp;lsquo;risk&amp;rsquo; as part of your assessment. &lt;a href=&#34;https://docs.google.com/document/d/1Qd5wrcTLuwQFIUvHgpvYUC889tk1XLnFsRRbkjvTYpU/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;Here is an example document&lt;/a&gt; you can use.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;work-through-the-unknowns&#34;&gt;🗒 Work through the unknowns&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do this over and over, until there is no more value to be gained in spending time on them.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;figure-out-who-and-which-teams-need-to-be-consulted&#34;&gt;🗣 Figure out who and which teams need to be consulted&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Then communicate as often as practical and/or relevant.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;run-the-project-and-adjust-the-plan-as-you-go&#34;&gt;📆 Run the project and adjust the plan as you go.&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How far has the project come?&lt;/li&gt;&#xA;&lt;li&gt;How far is it from completion?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t work &lt;em&gt;faster&lt;/em&gt; (and or &lt;em&gt;harder&lt;/em&gt;) when you discover the team is missing deadlines (e.g. &amp;ldquo;it&amp;rsquo;s ok, I know we missed this deadline/milestone, but we&amp;rsquo;re &lt;em&gt;sooooo&lt;/em&gt; close, let&amp;rsquo;s crank it up and get it done!&amp;rdquo;). &lt;strong&gt;STOP!&lt;/strong&gt; take a breath and understand why the deadline was missed. Were there any trending patterns that are likely to repeat themselves?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;track-changes-to-requirements&#34;&gt;📈 Track changes to requirements&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Be clear about the cost of those changes.&lt;/li&gt;&#xA;&lt;li&gt;How do these changes affect the completion?&lt;/li&gt;&#xA;&lt;li&gt;Should we cut some existing features in order to accommodate the new work?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;ensure-observability-and-monitoring-is-in-place&#34;&gt;📊 Ensure observability and monitoring is in place.&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Never release a product you can&amp;rsquo;t track out in the wild.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t forget your on-call process. Ensure monitors are in place.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;define-a-rollout-plan-and-what-the-roll-back-steps-look-like&#34;&gt;⛑ Define a rollout plan and what the roll back steps look like.&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What systems need to be integrated with?&lt;/li&gt;&#xA;&lt;li&gt;Notify appropriate on-call and support teams.&lt;/li&gt;&#xA;&lt;li&gt;Rollback plan can be a spreadsheet, word doc, doesn&amp;rsquo;t matter, just have one.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;retro&#34;&gt;❤️ Retro&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What went well, what didn&amp;rsquo;t, what could we do differently in future?&lt;/li&gt;&#xA;&lt;li&gt;Communicate with radical candor (care personally, challenge directly).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;celebrate&#34;&gt;🎉 CELEBRATE!&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Doesn&amp;rsquo;t matter how big or small the project, or whether it was difficult at times. Always, always, celebrate the finishing line and thank your team for their hard work.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;shielding&#34;&gt;Shielding&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t shield the team from issues that are arising around them (e.g. don&amp;rsquo;t think &amp;ldquo;oh, they&amp;rsquo;re stressed and missing deadlines, so I need to pretend like everything is ok&amp;rdquo; &amp;ndash; it&amp;rsquo;s not ok). Treat the team with respect, as adults, and let them know things aren&amp;rsquo;t working and that we need to adjust the process to resolve that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Yes, shield the team from &lt;em&gt;distractions&lt;/em&gt;, but that is something altogether different than shielding them from bombs exploding around them. They can help you negotiate those mindfields if you let them. We&amp;rsquo;re working with adults, and they don&amp;rsquo;t need to have scary things hidden from them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;positive-mindset&#34;&gt;Positive Mindset&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve found that swapping the word &amp;ldquo;problem&amp;rdquo; for &amp;ldquo;challenge&amp;rdquo; a good thing to do in general, whether it be talking about an actual technical challenge or discussing a challenging interaction with another employee.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The subtle switch in language helps me refocus on a more positive and motivated projectory (rather than setting myself up to be in a negative mindset for the conversation).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;recognising-trends&#34;&gt;Recognising Trends&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As time goes on, you might start having issues with your team (for various reasons - we&amp;rsquo;re humans, we&amp;rsquo;re notoriously difficult creatures).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When reporting to your line manager (e.g. 1:1&amp;rsquo;s where you discuss things that are on your mind), it can be difficult sometimes to voice concerns without explicit examples.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Depending on the situation, explicit examples aren&amp;rsquo;t always possible to recall. In those cases where you have a niggling feeling something isn&amp;rsquo;t quite right but you couldn&amp;rsquo;t point to an exact moment in time where an incident occurred, then being able to see a &lt;em&gt;trend&lt;/em&gt; of something negative happening can help you to raise it up to leadership.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Be aware of trends in people, otherwise you might find yourself in a bad situation and not sure how or why you got there in the first place. If you catch problems early enough, you can help work towards a solution that gets your team back on track.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;user-stories&#34;&gt;User Stories&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In case you&amp;rsquo;re not familiar with user stories&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Gherkin is plain-text with a little extra structure and is designed to be easy to learn by non-programmers, yet structured enough to allow concise description of examples to illustrate business rules in most real-world domains. &amp;ndash; &lt;a href=&#34;https://cucumber.io/docs/reference&#34; target=&#34;_blank&#34;&gt;https://cucumber.io/docs/reference&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;I find it&amp;rsquo;s good for documentation, but it can also be helpful to some teams to use these user stories as a foundation for their own integration testing systems (although I personally wouldn&amp;rsquo;t, I prefer just using them as a simple reference for what it is we want to achieve at a high-level).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example &amp;lsquo;feature&amp;rsquo;, broken down into various scenarios.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Feature: User Authentication&#xA;  &#xA;  ...optional description about this feature here...&#xA;&#xA;Scenario: authenticated user requesting a page&#xA;  Given I am a BuzzFeed user (internal or external)&#xA;  And I’m already signed in&#xA;  When I visit www.buzzfeed.com or www.buzzfeed.com/post&#xA;  Then I am directed to my destination page&#xA;&#xA;Scenario: unauthenticated user requesting a page&#xA;  Given I am a BuzzFeed user (internal or external)&#xA;  And I’m not signed in&#xA;  When I visit www.buzzfeed.com or www.buzzfeed.com/post&#xA;  Then I am able to login with &amp;lt;method&amp;gt;&#xA;&#xA;  Examples:&#xA;    | method            |&#xA;    | Facebook          |&#xA;    | Twitter           |&#xA;    | Google            |&#xA;    | Username/Password |&#xA;&#xA;Scenario: unauthenticated user successful login&#xA;  Given I am a BuzzFeed user (internal or external)&#xA;  And I provide valid credentials&#xA;  When I attempt to login&#xA;  Then I am directed to my destination page&#xA;&#xA;Scenario: unauthenticated user failed login&#xA;  Given I am a BuzzFeed user (internal or external)&#xA;  And I provide invalid credentials&#xA;  When I attempt to login&#xA;  Then I am presented with a login error&#xA;&#xA;Scenario: unauthenticated user sign-up&#xA;  Given I am a BuzzFeed user (internal or external)&#xA;  And I am not already registered in the system&#xA;  When I visit www.buzzfeed.com/cms&#xA;  Then I am directed to a legacy sign-up flow&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/project-management/</guid>
      <link>https://www.integralist.co.uk/posts/project-management/</link>
      <pubDate>Fri, 25 May 2018 00:00:00 +0000</pubDate>
      <title>Project Management in Five Minutes</title>
    </item>
    <item>
      <description>&lt;p&gt;I&amp;rsquo;ve long kept a list of books I&amp;rsquo;ve enjoyed reading, and decided I would share them as a blog post so others could benefit from their learnings.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I generally keep the &lt;a href=&#34;https://gist.github.com/Integralist/77877126a0b13766f0de&#34; target=&#34;_blank&#34;&gt;original gist&lt;/a&gt; the most up-to-date.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;algorithms&#34;&gt;Algorithms&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.manning.com/books/grokking-algorithms&#34; target=&#34;_blank&#34;&gt;Grokking Algorithms: An illustrated guide&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;best-practices&#34;&gt;Best Practices&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=wl_it_dp_o_pC_nS_nC?ie=UTF8&amp;amp;colid=1KPZ4BNV1OMC4&amp;amp;coliid=I1GJ3Q25TNFKN1&#34; target=&#34;_blank&#34;&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/The-Clean-Coder-Professional-Programmers/dp/0137081073/ref=wl_it_dp_o_pC_S_nC?ie=UTF8&amp;amp;colid=1KPZ4BNV1OMC4&amp;amp;coliid=IJUCNB9OWB7H8&#34; target=&#34;_blank&#34;&gt;The Clean Coder: A Code of Conduct for Professional Programmers&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;client-side&#34;&gt;Client-Side&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/CSS-Definitive-Guide-Eric-Meyer/dp/0596527330/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038313&amp;amp;sr=8-1&amp;amp;keywords=css+the+definitive+guide&#34; target=&#34;_blank&#34;&gt;CSS: The Definitive Guide&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Dont-Make-Me-Think-Usability/dp/0321965515/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038352&amp;amp;sr=8-1&amp;amp;keywords=dont+make+me+think&#34; target=&#34;_blank&#34;&gt;Don&amp;rsquo;t Make Me Think: A Common Sense Approach to Web Usability&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Even-Faster-Web-Sites-Performance/dp/0596522304/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038718&amp;amp;sr=8-1&amp;amp;keywords=even+faster+websites&#34; target=&#34;_blank&#34;&gt;Even Faster Web Sites: Performance Best Practices for Web Developers&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/High-Performance-Web-Sites-Essential/dp/0596529309/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038697&amp;amp;sr=8-1&amp;amp;keywords=High+Performance+Websites&#34; target=&#34;_blank&#34;&gt;High Performance Web Sites: Essential Knowledge for Front-End Engineers&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://abookapart.com/products/mobile-first&#34; target=&#34;_blank&#34;&gt;Mobile First&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://abookapart.com/products/responsible-responsive-design&#34; target=&#34;_blank&#34;&gt;Responsible Responsive Design&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://abookapart.com/products/responsive-web-design&#34; target=&#34;_blank&#34;&gt;Responsive Web Design&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;clojure&#34;&gt;Clojure&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Clojure-Brave-True-Ultimate-Programmer/dp/1593275919/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038088&amp;amp;sr=8-1&amp;amp;keywords=clojure+for+the+brave+and+true&#34; target=&#34;_blank&#34;&gt;Clojure for the Brave and True&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.apress.com/gb/book/9781484229514&#34; target=&#34;_blank&#34;&gt;Quick Clojure&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Joy-Clojure-Michael-Fogus/dp/1617291412/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038071&amp;amp;sr=8-1&amp;amp;keywords=joy+of+clojure&#34; target=&#34;_blank&#34;&gt;The Joy of Clojure&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;communication&#34;&gt;Communication&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.radicalcandor.com/&#34; target=&#34;_blank&#34;&gt;Radical Candor: care personally and challenge directly&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.nonviolentcommunication.com/&#34; target=&#34;_blank&#34;&gt;Nonviolent Communication&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.soundstrue.com/store/authentic-communication.html&#34; target=&#34;_blank&#34;&gt;Authentic Communication&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;concurrency&#34;&gt;Concurrency&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Programming-Concurrency-JVM-Mastering-Synchronization/dp/193435676X&#34; target=&#34;_blank&#34;&gt;Programming Concurrency on the JVM: Mastering Synchronization, STM, and Actors&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Seven-Concurrency-Models-Weeks-Programmers/dp/1937785653/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038041&amp;amp;sr=8-1&amp;amp;keywords=7+concurrency+models&#34; target=&#34;_blank&#34;&gt;Seven Concurrency Models in Seven Weeks: When Threads Unravel&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;culture&#34;&gt;Culture&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.soundstrue.com/store/conscious-business-4036.html&#34; target=&#34;_blank&#34;&gt;Conscious Business: How to build value through values&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://pattymccord.com/book/&#34; target=&#34;_blank&#34;&gt;Powerful: building a culture of freedom and responsibility&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;functional-programming&#34;&gt;Functional Programming&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Functional-Programming-Patterns-Scala-Clojure/dp/1937785475/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427039601&amp;amp;sr=8-1&amp;amp;keywords=functional+programming+patterns+in+scala+and+clojure&#34; target=&#34;_blank&#34;&gt;Functional Programming Patterns in Scala and Clojure&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Functional-Programming-Scala-Paul-Chiusano/dp/1617290653/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427039625&amp;amp;sr=8-1&amp;amp;keywords=functional+programming+in+scala&#34; target=&#34;_blank&#34;&gt;Functional Programming in Scala&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;go&#34;&gt;Go&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1453287896&amp;amp;sr=1-1&amp;amp;keywords=go+programming+language&#34; target=&#34;_blank&#34;&gt;The Go Programming Language&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;javascript&#34;&gt;JavaScript&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Eloquent-JavaScript-Modern-Introduction-Programming/dp/1593275846/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038759&amp;amp;sr=8-1&amp;amp;keywords=eloquent+javascript&#34; target=&#34;_blank&#34;&gt;Eloquent JavaScript: A Modern Introduction to Programming&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038840&amp;amp;sr=8-1&amp;amp;keywords=high+performance+javascript&#34; target=&#34;_blank&#34;&gt;High Performance JavaScript (Build Faster Web Application Interfaces)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038785&amp;amp;sr=8-1&amp;amp;keywords=javascript+the+good+parts&#34; target=&#34;_blank&#34;&gt;JavaScript: The Good Parts&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Driven-JavaScript-Development-Developers-Library/dp/0321683919/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038811&amp;amp;sr=8-1&amp;amp;keywords=test-driven+javascript+development&#34; target=&#34;_blank&#34;&gt;Test Driven JavaScript Development&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;management&#34;&gt;Management&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920056843.do&#34; target=&#34;_blank&#34;&gt;The Manager&amp;rsquo;s Path&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://managinghumans.com/pitch.html&#34; target=&#34;_blank&#34;&gt;Managing Humans: Biting and Humorous Tales of a Software Engineering Manager&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;patterns&#34;&gt;Patterns&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Mastering-Regular-Expressions-Jeffrey-Paperback/dp/B006DVFVTU/ref=sr_1_5?ie=UTF8&amp;amp;qid=1427038873&amp;amp;sr=8-5&amp;amp;keywords=mastering+regular+expressions&#34; target=&#34;_blank&#34;&gt;Mastering Regular Expressions&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;php&#34;&gt;PHP&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://practicaldesignpatternsinphp.com/&#34; target=&#34;_blank&#34;&gt;Practical Design Patterns in PHP&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;python&#34;&gt;Python&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.effectivepython.com/&#34; target=&#34;_blank&#34;&gt;Effective Python&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;ruby&#34;&gt;Ruby&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Beginning-Ruby-Novice-Professional-Experts/dp/1430223634/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038449&amp;amp;sr=8-1&amp;amp;keywords=beginning+ruby&#34; target=&#34;_blank&#34;&gt;Beginning Ruby: From Novice to Professional&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Design-Patterns-Ruby-Addison-Wesley-Professional/dp/0321490452/ref=wl_it_dp_o_pd_S_nC?ie=UTF8&amp;amp;colid=1KPZ4BNV1OMC4&amp;amp;coliid=I3ETXUMF5SXAB1&#34; target=&#34;_blank&#34;&gt;Design Patterns in Ruby&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Metaprogramming-Ruby-Program-Like-Facets/dp/1941222129/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038474&amp;amp;sr=8-1&amp;amp;keywords=metaprogramming+ruby&#34; target=&#34;_blank&#34;&gt;Metaprogramming Ruby&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Practical-Object-Oriented-Design-Ruby/dp/0321721330/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038609&amp;amp;sr=8-1&amp;amp;keywords=practical+object-oriented+design+in+ruby&#34; target=&#34;_blank&#34;&gt;Practical Object Oriented Design in Ruby&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Refactoring-Ruby-Addison-Wesley-Professional-ebook/dp/B002TIOYWG/ref=sr_1_1?ie=UTF8&amp;amp;qid=1385646915&amp;amp;sr=8-1&amp;amp;keywords=ruby+refactoring&#34; target=&#34;_blank&#34;&gt;Refactoring: Ruby Edition&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Sinatra-Up-Running-Alan-Harris/dp/1449304230/ref=sr_1_1?ie=UTF8&amp;amp;qid=1385656124&amp;amp;sr=8-1&amp;amp;keywords=Sinatra+-+Up+and+Running&#34; target=&#34;_blank&#34;&gt;Sinatra - Up and Running&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;shell&#34;&gt;Shell&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://shop.oreilly.com/product/9780596005955.do&#34; target=&#34;_blank&#34;&gt;Classic Shell Scripting&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;system-design-networking-and-security&#34;&gt;System Design, Networking and Security&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Amazon-Web-Services-Action-Andreas-Wittig/dp/1617292885/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1453287921&amp;amp;sr=1-1&amp;amp;keywords=aws+in+action&#34; target=&#34;_blank&#34;&gt;Amazon Web Services in Action&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Building-Microservices-Sam-Newman/dp/1491950358/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427039585&amp;amp;sr=8-1&amp;amp;keywords=Building+Microservices&#34; target=&#34;_blank&#34;&gt;Building Microservices&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Bulletproof-SSL-TLS-Ivan-Ristic/dp/1907117040/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038544&amp;amp;sr=8-1&amp;amp;keywords=Bulletproof+SSL+and+TLS&#34; target=&#34;_blank&#34;&gt;Bulletproof SSL and TLS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/High-Performance-Browser-Networking-performance/dp/1449344763/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427039463&amp;amp;sr=8-1&amp;amp;keywords=high+performance+browser+networking&#34; target=&#34;_blank&#34;&gt;High Performance Browser Networking&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Practice-Cloud-System-Administration-Distributed/dp/032194318X/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427039519&amp;amp;sr=8-1&amp;amp;keywords=the+practice+of+cloud+system+administration&#34; target=&#34;_blank&#34;&gt;The Practice of Cloud System Administration: Volume 2: Designing and Operating Large Distributed Systems&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Growing-Object-Oriented-Software-Guided-Signature/dp/0321503627/ref=sr_1_1?ie=UTF8&amp;amp;qid=1385655342&amp;amp;sr=8-1&amp;amp;keywords=Growing+Object+Oriented+Software+Guided+by+Tests&#34; target=&#34;_blank&#34;&gt;Growing Object Oriented Software Guided by Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;tools&#34;&gt;Tools&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Pro-Vim-Mark-McDonnell/dp/1484202511/ref=sr_1_1?ie=UTF8&amp;amp;qid=1427038180&amp;amp;sr=8-1&amp;amp;keywords=pro+vim&#34; target=&#34;_blank&#34;&gt;Pro Vim&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920026358.do&#34; target=&#34;_blank&#34;&gt;Vagrant: Up and Running&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.amazon.co.uk/Version-Control-Git-collaborative-development/dp/1449316387/ref=sr_1_1?ie=UTF8&amp;amp;qid=1385647089&amp;amp;sr=8-1&amp;amp;keywords=version+control+with+git&#34; target=&#34;_blank&#34;&gt;Version Control with Git: Powerful tools and techniques for collaborative software development&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/reading-list/</guid>
      <link>https://www.integralist.co.uk/posts/reading-list/</link>
      <pubDate>Fri, 25 May 2018 00:00:00 +0000</pubDate>
      <title>Engineering and Tech Recommended Reading List</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I recently implemented a Python library which acts as an abstraction layer on top of an existing security algorithm (in this case &lt;a href=&#34;https://www.tarsnap.com/scrypt.html&#34; target=&#34;_blank&#34;&gt;scrypt&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The motivation was for allowing teams to have a consistent experience utilising encryption (and hashing) in their applications and services without necessarily having to know the ins-and-outs of what&amp;rsquo;s important with regards to salts, key lengths etc.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I always encourage people to understand what it is they&amp;rsquo;re doing, but in some cases that&amp;rsquo;s not always a practical mindset.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The library provides three functions:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;generate_digest&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;decrypt_digest&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;validate_digest&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;{{&amp;lt; adverts/pythonforprogrammers &amp;gt;}}&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Before we start looking at the three functions provided by this library/interface, let&amp;rsquo;s very briefly talk about KDF and PBKDF2.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A &lt;a href=&#34;https://en.wikipedia.org/wiki/Key_derivation_function&#34; target=&#34;_blank&#34;&gt;KDF&lt;/a&gt; (Key Derivation Function) accepts a message + a key, and produces a digest for its output. They are designed to be more computationally intensive than standard hashing functions, and so they make it harder to use dictionary or rainbow table style attacks (as they would require a lot of extra memory resources and become more unfeasible as an attack vector).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By default the KDF will generate a random salt (thus output is non-deterministic) and have a maximum computational time of &lt;code&gt;0.5&lt;/code&gt; (although this can be overridden using a &lt;code&gt;maxtime&lt;/code&gt; argument, as we&amp;rsquo;ll see later).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A &lt;a href=&#34;https://en.wikipedia.org/wiki/PBKDF2&#34; target=&#34;_blank&#34;&gt;PBKDF2&lt;/a&gt; on the other hand is able to provide deterministic output (as well as the ability to specify an explicit salt value). The internal implementation will repeat its process multiple times, thus reducing the feasibility of automated password cracking attempts (similar to a KDF).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I mention both of these (KDF and PBKDF2) because the &lt;code&gt;generate_digest&lt;/code&gt; function I&amp;rsquo;ve written is a multi-arity function that will switch implementation based upon the provided arguments in the method signature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Originally I had two separate functions to distinguish them a bit more clearly but realised if this library is to make life easier for developers who don&amp;rsquo;t understand encryption or hashing concepts, then I need to provide a single function that intelligently handles things internally.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because KDF accepts a key and is able to return the original message (given the same key) it&amp;rsquo;s acting as a form of symmetrical encryption, whereas a PBKDF2 is more like a one-way hash function. Hence I named the function in this library &lt;code&gt;generate_digest&lt;/code&gt; rather than something like &lt;code&gt;encrypt_message&lt;/code&gt; which wouldn&amp;rsquo;t have made sense when dealing with PBKDF2.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;generate-digest&#34;&gt;generate_digest&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a multi-arity function that will generate a digest using either a password-based key derivation function (&lt;a href=&#34;https://en.wikipedia.org/wiki/Key_derivation_function&#34; target=&#34;_blank&#34;&gt;KDF&lt;/a&gt;) or a &lt;a href=&#34;https://en.wikipedia.org/wiki/PBKDF2&#34; target=&#34;_blank&#34;&gt;PBKDF2&lt;/a&gt; depending on the input given.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a &lt;code&gt;password&lt;/code&gt; argument is provided, then KDF will be used (along with a random salt) to generate a &lt;em&gt;non-deterministic&lt;/em&gt; digest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a &lt;code&gt;salt&lt;/code&gt; is provided, then a PBKDF2 will be used to generate a &lt;em&gt;deterministic&lt;/em&gt; digest.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;salts should be a minimum of 128bits (~16 characters) in length. Also, when specifying a maxtime with &lt;code&gt;generate_digest&lt;/code&gt;, ensure you include that same value when decrypting with &lt;code&gt;decrypt_digest&lt;/code&gt; or validating via &lt;code&gt;validate_digest&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;decrypt-digest-and-validate-digest&#34;&gt;decrypt_digest and validate_digest&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;decrypt_digest&lt;/code&gt; and &lt;code&gt;validate_digest&lt;/code&gt; functions only apply to digests that have been generated using a password (i.e. KDF). Given the right password &lt;code&gt;decrypt_digest&lt;/code&gt; will return the original message, and thus is considered more a form of symmetrical encryption than a straight one-way hash function. The &lt;code&gt;validate_digest&lt;/code&gt; function will return a boolean true or false if the given password was able to decrypt the message.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dependencies&#34;&gt;Dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This abstraction library requires &lt;code&gt;scrypt&lt;/code&gt;, which itself requires the following dependencies to be installed within the context of your service: &lt;code&gt;build-essential&lt;/code&gt;, &lt;code&gt;libssl-dev&lt;/code&gt;, and &lt;code&gt;python-dev&lt;/code&gt;. If your service has a Dockerfile, adding these dependencies should be as simple as adding a line like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y build-essential libssl-dev python-dev&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I suggest looking at the test suite (see below) to get an idea of how you would use the functions in this library.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for a glossary of security terms, refer to &lt;a href=&#34;https://docs.google.com/document/d/1qs3jEIQvocdVhSxCSPLF1BoLnp91aLnuUIasvl-maYo/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;this document&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;tests&#34;&gt;Tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before we look at the implementation of the library, let&amp;rsquo;s take a moment to sift through its test suite.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I named the library &lt;code&gt;secure&lt;/code&gt; and have it running on a private PyPy instance. This code is &lt;a href=&#34;https://github.com/Integralist/Python-Encryption&#34; target=&#34;_blank&#34;&gt;made available via GitHub&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import pytest&#xA;&#xA;from secure.interface import ArgumentError, generate_digest, validate_digest, decrypt_digest&#xA;&#xA;&#xA;message = &amp;quot;my-message&amp;quot;&#xA;password = &amp;quot;my-password&amp;quot;&#xA;salt = &amp;quot;my-salt-is-long-enough&amp;quot;&#xA;&#xA;&#xA;def test_generate_digest_with_both_a_password_and_a_salt():&#xA;    &amp;quot;&amp;quot;&amp;quot;Providing both a password and a salt should raise an exception.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    with pytest.raises(ArgumentError):&#xA;        generate_digest(message, salt=salt, password=password)&#xA;&#xA;&#xA;def test_generate_digest_with_a_password():&#xA;    &amp;quot;&amp;quot;&amp;quot;Generating a digest with a password should be non-deterministic.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    digest1 = generate_digest(message, password=password)&#xA;    digest2 = generate_digest(message, password=password)&#xA;    digest3 = generate_digest(message, password=password, maxtime=1.5)&#xA;    digest4 = generate_digest(message, password=password, maxtime=1.5)&#xA;    digest5 = generate_digest(message, password=password, maxtime=int(1))&#xA;    digest6 = generate_digest(message, password=password, maxtime=int(1))&#xA;&#xA;    assert digest1 != digest2&#xA;    assert digest3 != digest4&#xA;    assert digest5 != digest6&#xA;&#xA;&#xA;def test_generate_digest_without_a_password():&#xA;    &amp;quot;&amp;quot;&amp;quot;Generating a digest without a password should be deterministic.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    digest1 = generate_digest(message)&#xA;    digest2 = generate_digest(message)&#xA;    digest3 = generate_digest(message, salt=salt)&#xA;    digest4 = generate_digest(message, salt=salt)&#xA;    digest5 = generate_digest(message, length=128)&#xA;    digest6 = generate_digest(message, length=128)&#xA;&#xA;    assert digest1 == digest2&#xA;    assert digest3 == digest4&#xA;    assert len(digest5) == len(digest6)&#xA;&#xA;&#xA;def test_generate_digest_with_different_salt_lengths():&#xA;    &amp;quot;&amp;quot;&amp;quot;Salts should be at least 128bits (~16 characters) in length.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    generate_digest(message, salt=salt)&#xA;&#xA;    with pytest.raises(ArgumentError):&#xA;        generate_digest(message, salt=&amp;quot;too-short&amp;quot;)&#xA;&#xA;def test_validate_digest():&#xA;    &amp;quot;&amp;quot;&amp;quot;Validation only applies to digests generated with a password.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    digest1 = generate_digest(message, password=password)&#xA;    digest2 = generate_digest(message, password=password)&#xA;    digest3 = generate_digest(message, password=password, maxtime=1.5)&#xA;    digest4 = generate_digest(message, password=password, maxtime=1.5)&#xA;    digest5 = generate_digest(message, password=password, maxtime=int(1))&#xA;    digest6 = generate_digest(message, password=password, maxtime=int(1))&#xA;&#xA;    assert not validate_digest(digest1, &#39;incorrect-password&#39;)&#xA;    assert validate_digest(digest1, password)&#xA;    assert validate_digest(digest3, password, maxtime=1.5)&#xA;    assert validate_digest(digest5, password, maxtime=int(1))&#xA;&#xA;&#xA;def test_decrypt_digest():&#xA;    &amp;quot;&amp;quot;&amp;quot;Decryption is possible given the right password.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    digest = generate_digest(message, password=password)&#xA;&#xA;    assert decrypt_digest(digest, password) == message&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, time to see the library code itself.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I like to use &lt;a href=&#34;http://mypy-lang.org/&#34; target=&#34;_blank&#34;&gt;MyPy&lt;/a&gt; for type hinting.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import scrypt&#xA;&#xA;from typing import Union&#xA;&#xA;&#xA;class ArgumentError(Exception):&#xA;    pass&#xA;&#xA;&#xA;def generate_digest(message: str,&#xA;                    password: str = None,&#xA;                    maxtime: Union[float, int] = 0.5,&#xA;                    salt: str = &amp;quot;&amp;quot;,&#xA;                    length: int = 64) -&amp;gt; bytes:&#xA;    &amp;quot;&amp;quot;&amp;quot;Multi-arity function for generating a digest.&#xA;&#xA;    Use KDF symmetric encryption given a password.&#xA;    Use deterministic hash function given a salt (or lack of password).&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    if password and salt:&#xA;        raise ArgumentError(&amp;quot;only provide a password or a salt, not both&amp;quot;)&#xA;&#xA;    if salt != &amp;quot;&amp;quot; and len(salt) &amp;lt; 16:&#xA;        raise ArgumentError(&amp;quot;salts need to be minimum of 128bits (~16 characters)&amp;quot;)&#xA;&#xA;    if password:&#xA;        return scrypt.encrypt(message, password, maxtime=maxtime)&#xA;    else:&#xA;        return scrypt.hash(message, salt, buflen=length)&#xA;&#xA;&#xA;def decrypt_digest(digest: bytes,&#xA;                   password: str,&#xA;                   maxtime: Union[float, int] = 0.5) -&amp;gt; bytes:&#xA;    &amp;quot;&amp;quot;&amp;quot;Decrypts digest using given password.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    return scrypt.decrypt(digest, password, maxtime)&#xA;&#xA;&#xA;def validate_digest(digest: bytes,&#xA;                    password: str,&#xA;                    maxtime: Union[float, int] = 0.5) -&amp;gt; bool:&#xA;    &amp;quot;&amp;quot;&amp;quot;Validate digest using given password.&amp;quot;&amp;quot;&amp;quot;&#xA;&#xA;    try:&#xA;        scrypt.decrypt(digest, password, maxtime)&#xA;        return True&#xA;    except scrypt.error:&#xA;        return False&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let me know what you think on twitter. Have fun.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/python-security/</guid>
      <link>https://www.integralist.co.uk/posts/python-security/</link>
      <pubDate>Tue, 15 May 2018 00:00:00 +0000</pubDate>
      <title>Security with Python</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You have a statically generated website (like mine!) and you want to implement some kind of search facility that is:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Doesn&amp;rsquo;t Suck&lt;/strong&gt; (e.g. no ads or iframe)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Quick&lt;/strong&gt; (i.e. no server-side communication)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The solution is to use &lt;a href=&#34;https://lunrjs.com/&#34; target=&#34;_blank&#34;&gt;Lunr.js&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You might be wondering about Lunr&amp;rsquo;s origins? Well, it&amp;rsquo;s based loosely on the idea made popular by &lt;a href=&#34;https://lucene.apache.org/solr/&#34; target=&#34;_blank&#34;&gt;Solr&lt;/a&gt;, which is an open-source search platform built on a Java library called Lucene.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Since then we&amp;rsquo;ve also seen the release and rise of &lt;a href=&#34;https://www.elastic.co/products/elasticsearch&#34; target=&#34;_blank&#34;&gt;ElasticSearch&lt;/a&gt;, which is an open-source, distributed, and RESTful search engine built on top of the Apache Lucene library.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll explain this from the perspective of &lt;a href=&#34;https://gohugo.io/&#34; target=&#34;_blank&#34;&gt;Hugo&lt;/a&gt;, which is the static site generator I use to produce this website. Hugo stores the metadata for each post (e.g. title, date, categories, tags etc) in something it calls &lt;a href=&#34;https://gohugo.io/content-management/front-matter/&#34; target=&#34;_blank&#34;&gt;Front Matter&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I use YAML, but you can use JSON or TOML, and that&amp;rsquo;s important to note because the implementation I use is based on my metadata being in YAML format. So if yours is JSON or TOML, for example, then you&amp;rsquo;ll need to modify the code shown in this post to reflect your use case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is the &amp;lsquo;front matter&amp;rsquo; for this post you&amp;rsquo;re reading.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;---&#xA;title: &amp;quot;Static Search With Lunr.js&amp;quot;&#xA;date: 2018-05-10T16:54:08+01:00&#xA;categories:&#xA;  - &amp;quot;code&amp;quot;&#xA;  - &amp;quot;development&amp;quot;&#xA;  - &amp;quot;guide&amp;quot;&#xA;  - &amp;quot;search&amp;quot;&#xA;tags:&#xA;  - &amp;quot;elasticsearch&amp;quot;&#xA;  - &amp;quot;javascript&amp;quot;&#xA;  - &amp;quot;js&amp;quot;&#xA;  - &amp;quot;lunr&amp;quot;&#xA;  - &amp;quot;solr&amp;quot;&#xA;  - &amp;quot;static&amp;quot;&#xA;draft: false&#xA;---&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What typically follows the front matter is the content of your post.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tasks&#34;&gt;Tasks&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so here are the tasks we have to get a working solution:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Generate a search &lt;code&gt;index.json&lt;/code&gt; file.&lt;/li&gt;&#xA;&lt;li&gt;Create a search HTML page.&lt;/li&gt;&#xA;&lt;li&gt;Write some JavaScript to load the index JSON and populate Lunr.&lt;/li&gt;&#xA;&lt;li&gt;Write some &lt;em&gt;more&lt;/em&gt; JavaScript to accept user&amp;rsquo;s input.&lt;/li&gt;&#xA;&lt;li&gt;Write &lt;em&gt;even more&lt;/em&gt; JavaScript to query your index JSON.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not a JavaScript fan, but needs must.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;setup&#34;&gt;Setup&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;, generate an &lt;code&gt;index.json&lt;/code&gt; file. To do that I&amp;rsquo;m going to use &lt;a href=&#34;https://gruntjs.com/&#34; target=&#34;_blank&#34;&gt;Grunt&lt;/a&gt; because it ties easily into NPM&amp;rsquo;s &lt;code&gt;package.json&lt;/code&gt; format and luckily for me someone had already done a lot of the (no pun intended) &amp;lsquo;grunt&amp;rsquo; work and I just needed to modify the code to suit my needs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the relevant portion of the &lt;code&gt;package.json&lt;/code&gt; which we run with &lt;code&gt;npm run dev&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;scripts&amp;quot;: {&#xA;  &amp;quot;index&amp;quot;: &amp;quot;hugo &amp;amp;&amp;amp; grunt lunr-index&amp;quot;,&#xA;  &amp;quot;dev&amp;quot;: &amp;quot;npm run index &amp;amp;&amp;amp; hugo server&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is the &lt;code&gt;lunr-index&lt;/code&gt; Gruntfile task that&amp;rsquo;s executed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var yaml = require(&amp;quot;js-yaml&amp;quot;);&#xA;var S = require(&amp;quot;string&amp;quot;);&#xA;&#xA;var CONTENT_PATH_PREFIX = &amp;quot;content&amp;quot;;&#xA;&#xA;module.exports = function(grunt) {&#xA;&#xA;    grunt.registerTask(&amp;quot;lunr-index&amp;quot;, function() {&#xA;&#xA;        var indexPages = function() {&#xA;            var pagesIndex = [];&#xA;            grunt.file.recurse(CONTENT_PATH_PREFIX, function(abspath, rootdir, subdir, filename) {&#xA;                pagesIndex.push(processMDFile(abspath, filename));&#xA;            });&#xA;&#xA;            return pagesIndex;&#xA;        };&#xA;&#xA;        var processMDFile = function(abspath, filename) {&#xA;            var content = grunt.file.read(abspath);&#xA;            var pageIndex;&#xA;&#xA;            // separate the Front Matter from the content and parse it&#xA;            content = content.split(&amp;quot;---&amp;quot;);&#xA;&#xA;            var frontMatter;&#xA;            try {&#xA;                frontMatter = yaml.load(content[1]);&#xA;            } catch (e) {&#xA;                grunt.log.writeln(e.message);&#xA;            }&#xA;&#xA;            var href = S(abspath).chompLeft(CONTENT_PATH_PREFIX).chompRight(&amp;quot;.md&amp;quot;).s;&#xA;&#xA;            if (filename === &amp;quot;.DS_Store&amp;quot;) {&#xA;              return&#xA;            }&#xA;&#xA;            if (filename === &amp;quot;_index.md&amp;quot;) {&#xA;                href = &amp;quot;/&amp;quot;&#xA;            }&#xA;            var m = abspath.match(/^content\/page\/(.+)\.md/);&#xA;            if (m != null) {&#xA;              href = &amp;quot;/&amp;quot; + m[1]&#xA;            }&#xA;&#xA;            // build Lunr index for this page&#xA;            pageIndex = {&#xA;                title: frontMatter.title,&#xA;                tags: frontMatter.tags,&#xA;                href: href.toLowerCase(),&#xA;                content: S(content[2]).stripTags().stripPunctuation().s&#xA;            };&#xA;&#xA;            return pageIndex;&#xA;        };&#xA;&#xA;        grunt.file.write(&amp;quot;static/js/lunr/index.json&amp;quot;, JSON.stringify(indexPages()));&#xA;    });&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The key part to that Gruntfile, other than the parsing out of the metadata (front matter), is &lt;em&gt;where&lt;/em&gt; we store it: &lt;code&gt;static/js/lunr/index.json&lt;/code&gt;. That location is something that&amp;rsquo;s included in Hugo&amp;rsquo;s build step and so when I&amp;rsquo;m working locally on a new post I&amp;rsquo;ll use &lt;code&gt;npm run dev&lt;/code&gt; instead of &lt;code&gt;hugo server&lt;/code&gt; because I&amp;rsquo;m guaranteed to generate a new search index based on the latest blog content I&amp;rsquo;ve just added and that the file will always be available when my static code is deployed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;, create a search page:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;---&#xA;title: Search&#xA;description: Lookup articles of interest.&#xA;comments: false&#xA;menu: main&#xA;weight: -170&#xA;---&#xA;&#xA;&amp;lt;p&amp;gt;&amp;lt;input id=&amp;quot;search&amp;quot; type=&amp;quot;text&amp;quot; placeholder=&amp;quot;type something here&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;ul id=&amp;quot;results&amp;quot;&amp;gt;&amp;lt;/ul&amp;gt;&#xA;&#xA;&amp;lt;script src=&amp;quot;https://code.jquery.com/jquery-2.1.3.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&#xA;&amp;lt;script src=&amp;quot;https://unpkg.com/lunr/lunr.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&#xA;&amp;lt;script&amp;gt;&#xA;  ...script here...&#xA;&amp;lt;/script&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Step 3, 4, 5&lt;/strong&gt;, lots of JS&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var lunrIndex,&#xA;    $results,&#xA;    documents;&#xA;&#xA;function initLunr() {&#xA;  // retrieve the index file&#xA;  $.getJSON(&amp;quot;../../js/lunr/index.json&amp;quot;)&#xA;    .done(function(index) {&#xA;        documents = index;&#xA;&#xA;        lunrIndex = lunr(function(){&#xA;          this.ref(&#39;href&#39;)&#xA;          this.field(&#39;content&#39;)&#xA;&#xA;          this.field(&amp;quot;title&amp;quot;, {&#xA;              boost: 10&#xA;          });&#xA;&#xA;          this.field(&amp;quot;tags&amp;quot;, {&#xA;              boost: 5&#xA;          });&#xA;&#xA;          documents.forEach(function(doc) {&#xA;            try {&#xA;              this.add(doc)&#xA;            } catch (e) {}&#xA;          }, this)&#xA;        })&#xA;    })&#xA;    .fail(function(jqxhr, textStatus, error) {&#xA;        var err = textStatus + &amp;quot;, &amp;quot; + error;&#xA;        console.error(&amp;quot;Error getting Lunr index file:&amp;quot;, err);&#xA;    });&#xA;}&#xA;&#xA;function search(query) {&#xA;  return lunrIndex.search(query).map(function(result) {&#xA;    return documents.filter(function(page) {&#xA;      try {&#xA;        console.log(page)&#xA;        return page.href === result.ref;&#xA;      } catch (e) {&#xA;        console.log(&#39;whoops&#39;)&#xA;      }&#xA;    })[0];&#xA;  });&#xA;}&#xA;&#xA;function renderResults(results) {&#xA;  if (!results.length) {&#xA;    return;&#xA;  }&#xA;&#xA;  // show first ten results&#xA;  results.slice(0, 10).forEach(function(result) {&#xA;    var $result = $(&amp;quot;&amp;lt;li&amp;gt;&amp;quot;);&#xA;&#xA;    $result.append($(&amp;quot;&amp;lt;a&amp;gt;&amp;quot;, {&#xA;      href: result.href,&#xA;      text: &amp;quot;» &amp;quot; + result.title&#xA;    }));&#xA;&#xA;    $results.append($result);&#xA;  });&#xA;}&#xA;&#xA;function initUI() {&#xA;  $results = $(&amp;quot;#results&amp;quot;);&#xA;&#xA;  $(&amp;quot;#search&amp;quot;).keyup(function(){&#xA;    // empty previous results&#xA;    $results.empty();&#xA;&#xA;    // trigger search when at least two chars provided.&#xA;    var query = $(this).val();&#xA;    if (query.length &amp;lt; 2) {&#xA;      return;&#xA;    }&#xA;&#xA;    var results = search(query);&#xA;&#xA;    renderResults(results);&#xA;  });&#xA;}&#xA;&#xA;initLunr();&#xA;&#xA;$(document).ready(function(){&#xA;  initUI();&#xA;});&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The key part of the above JS is the bit after we&amp;rsquo;ve retrieved the search &lt;code&gt;index.json&lt;/code&gt; file, as this is what takes the search index file and uses it to populate Lunr:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;lunrIndex = lunr(function(){&#xA;  this.ref(&#39;href&#39;)&#xA;  this.field(&#39;content&#39;)&#xA;&#xA;  this.field(&amp;quot;title&amp;quot;, {&#xA;      boost: 10&#xA;  });&#xA;&#xA;  this.field(&amp;quot;tags&amp;quot;, {&#xA;      boost: 5&#xA;  });&#xA;&#xA;  documents.forEach(function(doc) {&#xA;    try {&#xA;      this.add(doc)&#xA;    } catch (e) {}&#xA;  }, this)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;and that&amp;rsquo;s it really.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/static-site-search/</guid>
      <link>https://www.integralist.co.uk/posts/static-site-search/</link>
      <pubDate>Thu, 10 May 2018 00:00:00 +0000</pubDate>
      <title>Static Search With Lunr.js</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I moved on from BuzzFeed October 2020 and Joined &lt;a href=&#34;https://www.fastly.com&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt;.&lt;br&gt;&#xA;See my &lt;a href=&#34;/resume/&#34;&gt;resume&lt;/a&gt; for details.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;An organisation reached out to me about whether I would like to work for them. The focus of this post &lt;strong&gt;&lt;em&gt;isn&amp;rsquo;t&lt;/em&gt;&lt;/strong&gt; that company (hence I&amp;rsquo;ve not mentioned their name), but more about a set of experiences I&amp;rsquo;ve had when changing jobs and how I think they&amp;rsquo;re important to keep in mind, along with specific topics of interest you should look to include, when considering future opportunities.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-happened&#34;&gt;What Happened?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A recruiter, let&amp;rsquo;s say they were calling on behalf of the &amp;ldquo;Foo&amp;rdquo; company, contacted me to say they (and their CTO) had stumbled across and enjoyed a selection of my blog posts, and found my profile on LinkedIn to fit the candidate they were looking for.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;my-current-work-situation&#34;&gt;My current work situation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I work at a company called &lt;a href=&#34;https://www.buzzfeed.com/&#34; target=&#34;_blank&#34;&gt;BuzzFeed&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve been here for almost two years now, and I came to them from the &lt;a href=&#34;http://www.bbc.co.uk/news&#34; target=&#34;_blank&#34;&gt;BBC&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;am-i-happy-at-buzzfeed&#34;&gt;Am I happy at BuzzFeed?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yes. 🙂&lt;/p&gt;&#xA;&#xA;&lt;p&gt;BuzzFeed is the first company I&amp;rsquo;ve worked for where they:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Treat me fair.&lt;/li&gt;&#xA;&lt;li&gt;Treat me like a human being.&lt;/li&gt;&#xA;&lt;li&gt;Support my need to work remotely.&lt;/li&gt;&#xA;&lt;li&gt;Are truly diverse and culturally supportive.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As far as interviewing, BuzzFeed also got brownie points for&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Paying me for my time interviewing with them.&lt;/li&gt;&#xA;&lt;li&gt;Paying for my accommodation and travel to NY (I live in the UK).&lt;/li&gt;&#xA;&lt;li&gt;Not taking advantage of me †&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† one example being, they already knew my salary and still increased it by a significant percentage&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;did-you-talk-to-the-foo-company&#34;&gt;Did you talk to the Foo company?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yes. I wanted to see how they compared.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-did-they-compare&#34;&gt;How &lt;em&gt;did&lt;/em&gt; they compare?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, I didn&amp;rsquo;t get past the initial conversation because they didn&amp;rsquo;t have a &amp;ldquo;remote role&amp;rdquo; for me, so I couldn&amp;rsquo;t say with 100% certainty how they would have compared.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But that said, there were some key aspects I took away from the conversation that I feel are worth mentioning, as these were specifically firing my internal alarm bell&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;They tried to sell me on &amp;ldquo;we&amp;rsquo;re &lt;strong&gt;all engineers&lt;/strong&gt; here&amp;rdquo;, which for me isn&amp;rsquo;t something we should be aspiring to (conversation for another day, but to me it&amp;rsquo;s an unhealthy attitude).&lt;/li&gt;&#xA;&lt;li&gt;There was a seeming &lt;strong&gt;lack of post-mortems and/or blameless culture&lt;/strong&gt;. Their response, if you can imagine it, was like a confused raised eye brow.&lt;/li&gt;&#xA;&lt;li&gt;They confused the concept of teams functioning differently to each other (which is fine) with &lt;strong&gt;inconsistency and lack of direction&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Money focused&lt;/strong&gt;. The biggest takeaway by far was they asked &lt;em&gt;constantly&lt;/em&gt; &amp;ldquo;What would it take for you to leave BuzzFeed?&amp;rdquo; †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No interest&lt;/strong&gt; in techniques that could help improve their ability to work more efficiently.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† I realised they cared less about me as a &amp;lsquo;person&amp;rsquo;, someone the company could build a long term relationship with, and more about me as a &amp;lsquo;number&amp;rsquo;. I was a resource, an entity they could own.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;what-was-the-problem&#34;&gt;What was the problem?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This company is (as they themselves stated) entirely made up of engineers, with the lightest touch of management. Through my discussion it became obvious that building new products with new tech was the focus and drive for those working there. But in that environment, being able to work &lt;em&gt;effectively&lt;/em&gt;, &lt;em&gt;efficiently&lt;/em&gt; and with &lt;em&gt;good communication&lt;/em&gt; (along with making sure you&amp;rsquo;re working on &lt;em&gt;the right thing&lt;/em&gt; and &lt;em&gt;at the right time&lt;/em&gt;) is not usually the case (in my experience).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me, I&amp;rsquo;m at a point in my career where discussions about programming languages or tech stack X isn&amp;rsquo;t something I worry about too much, or get giddy about, because most of the time it&amp;rsquo;s &lt;em&gt;how&lt;/em&gt; you solve a problem that&amp;rsquo;s important/interesting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In most situations, if you do your due diligence and exhaust all means available to you to make the given tech work, you should be able to empirically prove it&amp;rsquo;s not working, and thus are in a better position to justify a more appropriate language or tech stack. This all becomes trivial.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in my experience, people tend to fall back on subjective opinions and hand wavey &amp;lsquo;facts&amp;rsquo; rather than cracking on with solving the problem at hand.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Remember, we&amp;rsquo;re engineers, we can solve these issues in different ways. But I personally find the &amp;lsquo;human&amp;rsquo; problem is something that is typically much harder to solve and ultimately will cause a lot more detrimental effect on our ability to learn, progress in, and emotionally stay connected to our jobs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After my conversation with the Foo company I already had an unsettling feeling about them, but decided that I would do some research on Glassdoor to see if my gut feelings, stemming from the feedback I received, were correlating to other people&amp;rsquo;s past experiences working at the company. †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† it&amp;rsquo;s important to realise that with sites like Glassdoor you&amp;rsquo;re getting half the story, so take it with a pinch of salt. For me, I already had a lengthy conversation with the company and so I felt like I had enough information on which to corroborate my experience against.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Turns out my gut instincts right. Others, and by that I mean: engineers either working still (or who used to work), at Foo had voiced concerns that if you want to get paid lots of money to work on software with lots of tech debt, and with management that doesn&amp;rsquo;t care about improving the situation with how teams collaborate and/or communicate with each other, then company Foo might be the place for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, what I&amp;rsquo;m about to say, I can say because of privilege (I&amp;rsquo;m totally aware of that and I try to keep that in check wherever possible)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me, getting paid is important (because ultimately it allows me to look after my family), but in truth there&amp;rsquo;s more to life than getting paid which is (if not more) important for being happy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve been fortunate enough with my privilege to &lt;em&gt;be able&lt;/em&gt; to have that opinion, and I appreciate that for others this isn&amp;rsquo;t necessarily going to be the case, and so for those of you who don&amp;rsquo;t feel that way because of circumstances: that&amp;rsquo;s of course ok and valid. So with that in mind, I will cover what I feel are those &lt;em&gt;other&lt;/em&gt; important topics next&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-s-important-to-you&#34;&gt;What&amp;rsquo;s important to &lt;em&gt;you&lt;/em&gt;?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First, I want to take a moment to re-iterate, that you need to find what&amp;rsquo;s important &lt;em&gt;to you&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re starting out in your career, or your mid-way through, or you&amp;rsquo;re 20+ years in like me, then &lt;em&gt;your&lt;/em&gt; priorities, &lt;em&gt;your&lt;/em&gt; standards, and &lt;em&gt;your&lt;/em&gt; values are going to be different depending on the stage of life you&amp;rsquo;re at.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me (in a general sense), I&amp;rsquo;m looking for:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A well paid job (to enable me to support my family)&lt;/li&gt;&#xA;&lt;li&gt;A stable work environment (again, family)&lt;/li&gt;&#xA;&lt;li&gt;A diverse cultural environment (because diversity is important to me)&lt;/li&gt;&#xA;&lt;li&gt;To be able to have impact (I like helping people)&lt;/li&gt;&#xA;&lt;li&gt;To be happy (i.e. not stressed)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s be honest, who of us &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; looking for those qualities? Everyone wants a good paying job, everyone wants to be happy and in some cases most people prefer stability over chaos. Maybe diversity, or having an impact, isn&amp;rsquo;t high up on your list of things because you&amp;rsquo;re just starting out and to be honest, at that stage in life just &lt;em&gt;getting&lt;/em&gt; paid is probably going to be your highest priority.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At any rate, figure out &lt;em&gt;your&lt;/em&gt; priorities, &lt;em&gt;your&lt;/em&gt; standards and &lt;em&gt;your&lt;/em&gt; values, when considering working opportunities.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But also remember that these perspectives will change over time, and that&amp;rsquo;s ok too (sometimes we need stability in a fragile industry and nothing else).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-should-you-talk-about&#34;&gt;What should you talk about?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s a good idea, at the start of &lt;em&gt;any&lt;/em&gt; conversation, to ask:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;What&amp;rsquo;s the focus of today&amp;rsquo;s conversation?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;i.e. What&amp;rsquo;s important to the company (or individual) you&amp;rsquo;re talking with, and what insights do &lt;em&gt;they&lt;/em&gt; want to take from this? Does it align with your agenda? If not, clarify what &lt;em&gt;you&lt;/em&gt; hope to get out of the conversation, so it&amp;rsquo;s clear (on both sides) what intentions there are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Otherwise, here are the list of questions/topics I like to cover&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;What is the company&amp;rsquo;s story?&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Give me an insight into the company&amp;rsquo;s history/background.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Presence&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What number of offices do you have and what are their locality?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Culture and Diversity&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The company&amp;rsquo;s &amp;ldquo;values&amp;rdquo; will highlight what&amp;rsquo;s &lt;em&gt;important&lt;/em&gt; to them.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Hierarchy and Organisation Structure&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Are you &amp;lsquo;flat and lean&amp;rsquo; or &amp;lsquo;tall and fragmented&amp;rsquo;?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Visibility &amp;amp; Openness&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How does leadership share and handle critical/internal business topics?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Collaboration&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Building new features across different cross-discipline teams (avoiding duplication)&lt;/li&gt;&#xA;&lt;li&gt;Distributed Timezones&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Community&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How do internal &amp;amp; external staff interact?&lt;/li&gt;&#xA;&lt;li&gt;How do teams across offices/locality bond?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Process&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What&amp;rsquo;s your &amp;lsquo;onboarding&amp;rsquo; process?&lt;/li&gt;&#xA;&lt;li&gt;How are new features discussed, designed, evolved, released?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How do you deterimine a priority (e.g. impact/value for end-users)?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;What is the leadership like?&lt;/li&gt;&#xA;&lt;li&gt;How is documentation handled here?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do they care about documentation?&lt;/li&gt;&#xA;&lt;li&gt;Are they sharing information, or is there silos of knowledge?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Do you practice post mortems? (blameless retrospection, handling of failures)&lt;/li&gt;&#xA;&lt;li&gt;How do you handle tech debt (i.e. sustainability of your software)?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Communication&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What do you consider to be &lt;em&gt;good&lt;/em&gt; communication?&lt;/li&gt;&#xA;&lt;li&gt;Do you work with any of the following practices?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/24c8a9ce570d78d37ed0cf9967594e0e&#34; target=&#34;_blank&#34;&gt;SBI: Situation, Behaviour, Impact&lt;/a&gt; (Methodology, &lt;em&gt;The Center for Creative Leadership&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.radicalcandor.com/&#34; target=&#34;_blank&#34;&gt;Radical Candor&lt;/a&gt; (Book, &lt;em&gt;Kim Scott&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=IdMvWLARF1w&#34; target=&#34;_blank&#34;&gt;Conscious Business&lt;/a&gt; (Video, &lt;em&gt;Fred Kofman&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.soundstrue.com/store/authentic-communication.html&#34; target=&#34;_blank&#34;&gt;Authentic Communication&lt;/a&gt; (Book, &lt;em&gt;Fred Kofman&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Responsibility and Ownership&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What are your expectations of me when I start?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What is your indicator that I was a successful hire?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;What does the responsibilities look like for each of the following types of teams?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Engineering (Features/Products)&lt;/li&gt;&#xA;&lt;li&gt;Site Reliability&lt;/li&gt;&#xA;&lt;li&gt;Operations&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;How do teams work with regards to an &amp;lsquo;on-call&amp;rsquo; rota?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Job Progression &amp;amp; Opportunities&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Learning budgets?&lt;/li&gt;&#xA;&lt;li&gt;Conferences?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Remote Working&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How are remotes kept feeling included?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Work life balance and support&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How do staff balance their work-life?&lt;/li&gt;&#xA;&lt;li&gt;How do you work in a multi-region/distributed organisation?&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. cross-over hours between UK and US?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Tech&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;Finally&lt;/em&gt; we get to something engineering related&amp;hellip;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What does the infrastructure look like?&lt;/li&gt;&#xA;&lt;li&gt;What build systems do you use?&lt;/li&gt;&#xA;&lt;li&gt;What is your deployment platform?&lt;/li&gt;&#xA;&lt;li&gt;How often do/can you deploy?&lt;/li&gt;&#xA;&lt;li&gt;How do you handle rollback processes?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Vision and Future&lt;/strong&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Where is this company going?&lt;/li&gt;&#xA;&lt;li&gt;What are the end goals?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I think that pretty much covers everything of interest. To me at least these broad topics will give you a good indicator of what an organisation is like (or the &lt;em&gt;potential&lt;/em&gt; they have), depending on how they answer these questions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What do you ask in an interview? What matters to you? Let me know on twitter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/interview-topics/</guid>
      <link>https://www.integralist.co.uk/posts/interview-topics/</link>
      <pubDate>Sun, 08 Apr 2018 00:00:00 +0000</pubDate>
      <title>Interview Topics</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I was struggling to find a good (or just simple) reverse proxy solution written in &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;, so I decided to take what I had learnt from a work colleague of mine and put together a simple example for others to build upon if they needed a quick reference point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this example I have an origin server written in Python (for no other reason than to have a clearer distinction between the proxy and the origin) and which supports the endpoints &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/foo&lt;/code&gt; and &lt;code&gt;/bar/*&lt;/code&gt; (where the wildcard glob means we support multiple variants of that, such as &lt;code&gt;/bar/baz&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each origin handler will print the http request headers, followed by sending a response body that correlates to the handler name (so for example, the &lt;code&gt;FooHandler&lt;/code&gt; class will respond with &lt;code&gt;FOO!&lt;/code&gt;, while the &lt;code&gt;BarHandler&lt;/code&gt; class will response with &lt;code&gt;BAR!&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;example-python-origin-code&#34;&gt;Example Python Origin Code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is our Python code using the &lt;a href=&#34;http://www.tornadoweb.org/&#34; target=&#34;_blank&#34;&gt;Tornado&lt;/a&gt; web framework.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import tornado.ioloop&#xA;import tornado.web&#xA;&#xA;&#xA;class MainHandler(tornado.web.RequestHandler):&#xA;    def get(self):&#xA;        print(&amp;quot;MAIN HEADERS:\n\n&amp;quot;, self.request.headers)&#xA;        self.write(&amp;quot;MAIN!&amp;quot;)&#xA;&#xA;&#xA;class FooHandler(tornado.web.RequestHandler):&#xA;    def get(self):&#xA;        print(&amp;quot;FOO HEADERS:\n\n&amp;quot;, self.request.headers)&#xA;        self.write(&amp;quot;FOO!&amp;quot;)&#xA;&#xA;&#xA;class BarHandler(tornado.web.RequestHandler):&#xA;    def get(self):&#xA;        print(&amp;quot;BAR HEADERS:\n\n&amp;quot;, self.request.headers)&#xA;        self.write(&amp;quot;BAR!&amp;quot;)&#xA;&#xA;&#xA;def make_app():&#xA;    return tornado.web.Application([&#xA;        (r&amp;quot;/&amp;quot;, MainHandler),&#xA;        (r&amp;quot;/foo&amp;quot;, FooHandler),&#xA;        (r&amp;quot;/bar.*&amp;quot;, BarHandler),&#xA;    ])&#xA;&#xA;&#xA;if __name__ == &amp;quot;__main__&amp;quot;:&#xA;    app = make_app()&#xA;    app.listen(9000)&#xA;    tornado.ioloop.IOLoop.current().start()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;example-golang-proxy-code&#34;&gt;Example Golang Proxy Code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are two versions of the code, a simple version and a more advanced version that aims to handle more specific use cases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The simple version uses just the Go standard library, whereas the advanced version uses the standard library as well as a few a few external packages such as &lt;a href=&#34;https://github.com/julienschmidt/httprouter&#34; target=&#34;_blank&#34;&gt;httprouter&lt;/a&gt; and &lt;a href=&#34;https://github.com/Sirupsen/logrus&#34; target=&#34;_blank&#34;&gt;logrus&lt;/a&gt; for routing and logging respectively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One difference between them that&amp;rsquo;s worth mentioning is that in the simple version we use the &lt;code&gt;httputil.ReverseProxy&lt;/code&gt; http handler directly, whereas in the advanced version we use &lt;code&gt;httputil.NewSingleHostReverseProxy&lt;/code&gt; to construct this for us. The advanced version also tries to normalise the paths by stripping trailing slashes and joining them up with the base path (if there was one, although ironically I don&amp;rsquo;t define one in the advanced example).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;simple&#34;&gt;Simple&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httputil&amp;quot;&#xA;    &amp;quot;net/url&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    origin, _ := url.Parse(&amp;quot;http://localhost:9000/&amp;quot;)&#xA;&#xA;    director := func(req *http.Request) {&#xA;        req.Header.Add(&amp;quot;X-Forwarded-Host&amp;quot;, req.Host)&#xA;        req.Header.Add(&amp;quot;X-Origin-Host&amp;quot;, origin.Host)&#xA;        req.URL.Scheme = &amp;quot;http&amp;quot;&#xA;        req.URL.Host = origin.Host&#xA;    }&#xA;&#xA;    proxy := &amp;amp;httputil.ReverseProxy{Director: director}&#xA;&#xA;    http.HandleFunc(&amp;quot;/&amp;quot;, func(w http.ResponseWriter, r *http.Request) {&#xA;        proxy.ServeHTTP(w, r)&#xA;    })&#xA;&#xA;    log.Fatal(http.ListenAndServe(&amp;quot;:9001&amp;quot;, nil))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;advanced&#34;&gt;Advanced&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httputil&amp;quot;&#xA;    &amp;quot;net/url&amp;quot;&#xA;    &amp;quot;os&amp;quot;&#xA;    &amp;quot;strings&amp;quot;&#xA;&#xA;    &amp;quot;github.com/Sirupsen/logrus&amp;quot;&#xA;    &amp;quot;github.com/julienschmidt/httprouter&amp;quot;&#xA;)&#xA;&#xA;func singleJoiningSlash(a, b string) string {&#xA;    aslash := strings.HasSuffix(a, &amp;quot;/&amp;quot;)&#xA;    bslash := strings.HasPrefix(b, &amp;quot;/&amp;quot;)&#xA;    switch {&#xA;    case aslash &amp;amp;&amp;amp; bslash:&#xA;        return a + b[1:]&#xA;    case !aslash &amp;amp;&amp;amp; !bslash:&#xA;        return a + &amp;quot;/&amp;quot; + b&#xA;    }&#xA;    return a + b&#xA;}&#xA;&#xA;func main() {&#xA;    logrus.SetFormatter(&amp;amp;logrus.TextFormatter{})&#xA;    logrus.SetOutput(os.Stdout)&#xA;    logrus.SetLevel(logrus.InfoLevel)&#xA;    logger := logrus.WithFields(logrus.Fields{&#xA;        &amp;quot;service&amp;quot;: &amp;quot;go-reverse-proxy&amp;quot;,&#xA;    })&#xA;&#xA;    router := httprouter.New()&#xA;    origin, _ := url.Parse(&amp;quot;http://localhost:9000/&amp;quot;)&#xA;    path := &amp;quot;/*catchall&amp;quot;&#xA;&#xA;    reverseProxy := httputil.NewSingleHostReverseProxy(origin)&#xA;&#xA;    reverseProxy.Director = func(req *http.Request) {&#xA;        req.Header.Add(&amp;quot;X-Forwarded-Host&amp;quot;, req.Host)&#xA;        req.Header.Add(&amp;quot;X-Origin-Host&amp;quot;, origin.Host)&#xA;        req.URL.Scheme = origin.Scheme&#xA;        req.URL.Host = origin.Host&#xA;&#xA;        wildcardIndex := strings.IndexAny(path, &amp;quot;*&amp;quot;)&#xA;        proxyPath := singleJoiningSlash(origin.Path, req.URL.Path[wildcardIndex:])&#xA;        if strings.HasSuffix(proxyPath, &amp;quot;/&amp;quot;) &amp;amp;&amp;amp; len(proxyPath) &amp;gt; 1 {&#xA;            proxyPath = proxyPath[:len(proxyPath)-1]&#xA;        }&#xA;        req.URL.Path = proxyPath&#xA;    }&#xA;&#xA;    router.Handle(&amp;quot;GET&amp;quot;, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {&#xA;        reverseProxy.ServeHTTP(w, r)&#xA;    })&#xA;&#xA;    logger.Fatal(http.ListenAndServe(&amp;quot;:9001&amp;quot;, router))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;demonstration&#34;&gt;Demonstration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order to run this example you should follow these instructions:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;run the tornado application (e.g. &lt;code&gt;python tornado-origin.py&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;run the go application (e.g. &lt;code&gt;go run main.go&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;make http requests (shown below)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl -v http://localhost:9001/&#xA;curl -v http://localhost:9001/foo&#xA;curl -v http://localhost:9001/foo/&#xA;curl -v http://localhost:9001/bar/baz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should see output from the Python server that looks something like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FOO HEADERS:&#xA;&#xA;Host: localhost:9001&#xA;User-Agent: curl/7.54.0&#xA;Accept: */*&#xA;X-Forwarded-Host: localhost:9001&#xA;X-Origin-Host: localhost:9000&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;explanation&#34;&gt;Explanation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so let&amp;rsquo;s step through the &lt;code&gt;main&lt;/code&gt; function of the advanced example code to see what&amp;rsquo;s going on.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The core reverse proxy code and its concepts are effectively the same between the advanced and simple versions.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;First we set up our basic logging configuration:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;logrus.SetFormatter(&amp;amp;logrus.TextFormatter{})&#xA;logrus.SetOutput(os.Stdout)&#xA;logrus.SetLevel(logrus.InfoLevel)&#xA;logger := logrus.WithFields(logrus.Fields{&#xA;  &amp;quot;service&amp;quot;: &amp;quot;go-reverse-proxy&amp;quot;,&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next we create a new httprouter instance, we define the origin host (&lt;code&gt;http://localhost:9000/&lt;/code&gt;) and the &amp;lsquo;pattern&amp;rsquo; we want httprouter to look out for (&lt;code&gt;/*catchall&lt;/code&gt;, which is a special syntax that represents a catchall wildcard/glob):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;router := httprouter.New()&#xA;origin, _ := url.Parse(&amp;quot;http://localhost:9000/&amp;quot;)&#xA;path := &amp;quot;/*catchall&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next we create a new reverse proxy instance, passing it the origin host (&lt;code&gt;http://localhost:9000/&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;reverseProxy := httputil.NewSingleHostReverseProxy(origin)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Followed by configuring the &amp;lsquo;director&amp;rsquo; for the reverse proxy. The director is simply a function that modifies the received incoming request, while the response from the origin is copied back to the original client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this example, we attach a few common proxy related headers to the incoming request and then modify its Scheme/Host to reflect the origin we wish to proxy it onto.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, we change the request path to the origin. What we do is ensure the path we request from the origin is whatever the base origin path is + the requested path (i.e. not just directing the request to the root/entrypoint of the origin).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In our example, our origin&amp;rsquo;s path is just &lt;code&gt;/&lt;/code&gt; whereas the client will be requesting things like &lt;code&gt;/foo&lt;/code&gt; and &lt;code&gt;/bar/baz&lt;/code&gt;, so these would be appended to the origin&amp;rsquo;s defined &lt;code&gt;/&lt;/code&gt;. But we also make sure that when joining the origin&amp;rsquo;s path with the incoming request path, that we avoid double slashes in the middle.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, we ensure that any trailing slash is removed as well:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;reverseProxy.Director = func(req *http.Request) {&#xA;  req.Header.Add(&amp;quot;X-Forwarded-Host&amp;quot;, req.Host)&#xA;  req.Header.Add(&amp;quot;X-Origin-Host&amp;quot;, origin.Host)&#xA;  req.URL.Scheme = origin.Scheme&#xA;  req.URL.Host = origin.Host&#xA;&#xA;  wildcardIndex := strings.IndexAny(path, &amp;quot;*&amp;quot;)&#xA;  proxyPath := singleJoiningSlash(origin.Path, req.URL.Path[wildcardIndex:])&#xA;  if strings.HasSuffix(proxyPath, &amp;quot;/&amp;quot;) &amp;amp;&amp;amp; len(proxyPath) &amp;gt; 1 {&#xA;    proxyPath = proxyPath[:len(proxyPath)-1]&#xA;  }&#xA;  req.URL.Path = proxyPath&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, we setup the handler for the &lt;code&gt;/*catchall&lt;/code&gt; httprouter path. In this case we don&amp;rsquo;t do anything other than call the reverse proxy&amp;rsquo;s &lt;code&gt;ServeHTTP&lt;/code&gt; method and pass it the original &lt;code&gt;ResponseWriter&lt;/code&gt; and http &lt;code&gt;Request&lt;/code&gt;. We then kick start the httprouter using &lt;code&gt;ListenAndServe&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;router.Handle(&amp;quot;GET&amp;quot;, path, func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {&#xA;  reverseProxy.ServeHTTP(w, r)&#xA;})&#xA;&#xA;logger.Fatal(http.ListenAndServe(&amp;quot;:9001&amp;quot;, router))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;handling-errors&#34;&gt;Handling Errors&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order to handle errors the reverse proxy needs to construct a &lt;em&gt;new&lt;/em&gt; response object, which means if you wanted the error response you generate to have all the same response headers as were provided by the upstream service, then you&amp;rsquo;d have to programmatically add those to the new response object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see how we can handle errors in the basic sense, just to get an idea for how the code looks. Now we don&amp;rsquo;t need to use another programming language to do this, we can do it all in Go (we could have done this earlier instead of using Python, but I wanted to highlight how you &lt;em&gt;could&lt;/em&gt; use another language if you wanted).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;errors&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;net&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httptest&amp;quot;&#xA;    &amp;quot;net/http/httputil&amp;quot;&#xA;    &amp;quot;net/url&amp;quot;&#xA;    &amp;quot;strings&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;// copied from https://golang.org/src/net/http/httputil/reverseproxy.go?s=3330:3391#L98&#xA;func singleJoiningSlash(a, b string) string {&#xA;    aslash := strings.HasSuffix(a, &amp;quot;/&amp;quot;)&#xA;    bslash := strings.HasPrefix(b, &amp;quot;/&amp;quot;)&#xA;    switch {&#xA;    case aslash &amp;amp;&amp;amp; bslash:&#xA;        return a + b[1:]&#xA;    case !aslash &amp;amp;&amp;amp; !bslash:&#xA;        return a + &amp;quot;/&amp;quot; + b&#xA;    }&#xA;    return a + b&#xA;}&#xA;&#xA;func main() {&#xA;    backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        fmt.Fprintln(w, &amp;quot;backend server handled the request!&amp;quot;)&#xA;    }))&#xA;    defer backendServer.Close()&#xA;&#xA;    backendServerURL, err := url.Parse(backendServer.URL)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    proxy := &amp;amp;httputil.ReverseProxy{&#xA;        Director: func(r *http.Request) {&#xA;            r.URL.Scheme = backendServerURL.Scheme&#xA;            r.URL.Host = backendServerURL.Host&#xA;            r.URL.Path = singleJoiningSlash(backendServerURL.Path, r.URL.Path)&#xA;        },&#xA;        Transport: &amp;amp;http.Transport{&#xA;            Dial: (&amp;amp;net.Dialer{&#xA;                Timeout: 10 * time.Second,&#xA;            }).Dial,&#xA;        },&#xA;        ModifyResponse: func(r *http.Response) error {&#xA;            // return nil&#xA;            //&#xA;            // purposefully return an error so ErrorHandler gets called&#xA;            return errors.New(&amp;quot;uh-oh&amp;quot;)&#xA;        },&#xA;        ErrorHandler: func(rw http.ResponseWriter, r *http.Request, err error) {&#xA;            fmt.Printf(&amp;quot;error was: %+v&amp;quot;, err)&#xA;            rw.WriteHeader(http.StatusInternalServerError)&#xA;            rw.Write([]byte(err.Error()))&#xA;        },&#xA;    }&#xA;&#xA;    frontendServer := httptest.NewServer(proxy)&#xA;    defer frontendServer.Close()&#xA;&#xA;    resp, err := http.Get(frontendServer.URL)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    b, err := ioutil.ReadAll(resp.Body)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    fmt.Printf(&amp;quot;\n\nbody: \n%s\n\n&amp;quot;, b)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here we can see that our &lt;code&gt;httputil.ReverseProxy#ModifyResponse&lt;/code&gt; function is hardcoded to return an error type, which then causes the &lt;code&gt;httputil.ReverseProxy#ErrorHandler&lt;/code&gt; function to be called.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there we use the &lt;code&gt;http.ResponseWriter&lt;/code&gt; to create a &lt;em&gt;new&lt;/em&gt; response. In this case we do nothing other than print the original error, but you could do pretty much anything you like at this point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you needed the original response object that came from the upstream then you&amp;rsquo;d need to make sure the error you returned from &lt;code&gt;ModifyResponse&lt;/code&gt; was a custom error type so that you attach a field such as &lt;code&gt;OriginalResponse&lt;/code&gt; to it and thus assign it the original &lt;code&gt;http.Response&lt;/code&gt; that was available to you within &lt;code&gt;ModifyResponse&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;nginx-lite-not-really&#34;&gt;NGINX-Lite (not-really)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is an example that demonstrates using &lt;a href=&#34;https://httpbin.org/&#34; target=&#34;_blank&#34;&gt;httpbin&lt;/a&gt; as our origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically we use its &lt;code&gt;/anything&lt;/code&gt; endpoint, which allows you to provide any value as the final path segment. So for example, &lt;code&gt;/anything/foo&lt;/code&gt; or &lt;code&gt;/anything/beep&lt;/code&gt;, both work with the &lt;code&gt;httpbin.org&lt;/code&gt; service.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httputil&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    proxy := &amp;amp;httputil.ReverseProxy{Director: func(req *http.Request) {&#xA;        originHost := &amp;quot;httpbin.org&amp;quot;&#xA;        originPathPrefix := &amp;quot;/anything&amp;quot;&#xA;&#xA;        req.Header.Add(&amp;quot;X-Forwarded-Host&amp;quot;, req.Host)&#xA;        req.Header.Add(&amp;quot;X-Origin-Host&amp;quot;, originHost)&#xA;        req.Host = originHost&#xA;        req.URL.Scheme = &amp;quot;https&amp;quot;&#xA;        req.URL.Host = originHost&#xA;        req.URL.Path = originPathPrefix + req.URL.Path&#xA;&#xA;        fmt.Printf(&amp;quot;final request\n\n %+v \n\n&amp;quot;, req)&#xA;    }}&#xA;&#xA;    http.HandleFunc(&amp;quot;/&amp;quot;, func(w http.ResponseWriter, r *http.Request) {&#xA;        proxy.ServeHTTP(w, r)&#xA;    })&#xA;&#xA;    log.Fatal(http.ListenAndServe(&amp;quot;:9001&amp;quot;, nil))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s elaborate on this example a little bit and ensure that our reverse proxy has a client timeout specified (see &lt;a href=&#34;https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt; for details as to why you would want to do this).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also use &lt;code&gt;gorilla/mux&lt;/code&gt; as it supports utilising regular expression path matching (we could do this ourselves, but using a library in this case helps to keep the code we have to write down).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One last thing you&amp;rsquo;ll notice is that we&amp;rsquo;re using a configuration object that allows us to configure &lt;em&gt;override&lt;/em&gt; behaviour. For example, if our request includes a HTTP header of &lt;code&gt;X-BF-Testing&lt;/code&gt; and its value is &lt;code&gt;integralist&lt;/code&gt;, then we&amp;rsquo;ll proxy the request to a different endpoint.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can do more complex things if necessary, but this gives you a good idea of how to replicate something like NGINX with very little code (obviously to replicate something like NGINX is &lt;em&gt;waaay&lt;/em&gt; beyond the scope of this post) 😉&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;net&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httputil&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;&#xA;    &amp;quot;github.com/gorilla/mux&amp;quot;&#xA;)&#xA;&#xA;type override struct {&#xA;    Header string&#xA;    Match  string&#xA;    Host   string&#xA;    Path   string&#xA;}&#xA;&#xA;type config struct {&#xA;    Path     string&#xA;    Host     string&#xA;    Override override&#xA;}&#xA;&#xA;func generateProxy(conf config) http.Handler {&#xA;    proxy := &amp;amp;httputil.ReverseProxy{Director: func(req *http.Request) {&#xA;        originHost := conf.Host&#xA;        req.Header.Add(&amp;quot;X-Forwarded-Host&amp;quot;, req.Host)&#xA;        req.Header.Add(&amp;quot;X-Origin-Host&amp;quot;, originHost)&#xA;        req.Host = originHost&#xA;        req.URL.Host = originHost&#xA;        req.URL.Scheme = &amp;quot;https&amp;quot;&#xA;&#xA;        if conf.Override.Header != &amp;quot;&amp;quot; &amp;amp;&amp;amp; conf.Override.Match != &amp;quot;&amp;quot; {&#xA;            if req.Header.Get(conf.Override.Header) == conf.Override.Match {&#xA;                req.URL.Path = conf.Override.Path&#xA;            }&#xA;        }&#xA;    }, Transport: &amp;amp;http.Transport{&#xA;        Dial: (&amp;amp;net.Dialer{&#xA;            Timeout: 5 * time.Second,&#xA;        }).Dial,&#xA;    }}&#xA;&#xA;    return proxy&#xA;}&#xA;&#xA;func main() {&#xA;    r := mux.NewRouter()&#xA;&#xA;    configuration := []config{&#xA;        config{&#xA;            Path: &amp;quot;/{path:anything/(?:foo|bar)}&amp;quot;,&#xA;            Host: &amp;quot;httpbin.org&amp;quot;,&#xA;        },&#xA;        config{&#xA;            Path: &amp;quot;/anything/foobar&amp;quot;,&#xA;            Host: &amp;quot;httpbin.org&amp;quot;,&#xA;            Override: override{&#xA;                Header: &amp;quot;X-BF-Testing&amp;quot;,&#xA;                Match:  &amp;quot;integralist&amp;quot;,&#xA;                Path:   &amp;quot;/anything/newthing&amp;quot;,&#xA;            },&#xA;        },&#xA;    }&#xA;&#xA;    for _, conf := range configuration {&#xA;        proxy := generateProxy(conf)&#xA;&#xA;        r.HandleFunc(conf.Path, func(w http.ResponseWriter, r *http.Request) {&#xA;            proxy.ServeHTTP(w, r)&#xA;        })&#xA;    }&#xA;&#xA;    log.Fatal(http.ListenAndServe(&amp;quot;:9001&amp;quot;, r))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s all there is to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You could also wrap the function passed to &lt;code&gt;router.Handle&lt;/code&gt; in a middleware function so that you&amp;rsquo;re able to do extra processing. A common example of this is to authenticate the incoming request &lt;em&gt;before&lt;/em&gt; it is proxied to the origin (meaning you can reject the request if necessary).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-reverse-proxy/</guid>
      <link>https://www.integralist.co.uk/posts/go-reverse-proxy/</link>
      <pubDate>Sat, 03 Mar 2018 00:00:00 +0000</pubDate>
      <title>Go Reverse Proxy</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve &lt;a href=&#34;/posts/security-basics/&#34;&gt;written previously&lt;/a&gt; (and in-depth) on the subject&#xA;of security basics, using tools such as GPG, OpenSSH, OpenSSL, and Keybase. But&#xA;this time I wanted to focus in on the differences between encryption and&#xA;hashing, whilst also providing a slightly more concise reference point for those&#xA;already familiar with these concepts.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so using the correct terminology is essential and helps us to be explicit&#xA;and clear with what we really mean.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;hash function&lt;/strong&gt;:&lt;br&gt;&#xA;calculates a deterministic, irreversible, fixed-size alphanumeric string (based on input).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;message&lt;/strong&gt;:&lt;br&gt;&#xA;a message &lt;em&gt;is&lt;/em&gt; the data (e.g. the &amp;lsquo;input&amp;rsquo; provided to a hash function).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;digest&lt;/strong&gt;:&lt;br&gt;&#xA;the hexidecimal output generated by a hash function (contextually referred to as &amp;ldquo;checksum&amp;rdquo; or &amp;ldquo;fingerprint&amp;rdquo;).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;symmetric algorithm&lt;/strong&gt;:&lt;br&gt;&#xA;a cryptographic algorithm that uses the same key to encrypt and decrypt data.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;asymmetric algorithm&lt;/strong&gt;:&lt;br&gt;&#xA;a form of encryption where keys come in pairs (what one key encrypts, only the other can decrypt).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;integrity&lt;/strong&gt;:&lt;br&gt;&#xA;the message transported has not been tampered with or altered.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;confidentiality&lt;/strong&gt;:&lt;br&gt;&#xA;the communication between trusted parties is confidential.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;authenticity&lt;/strong&gt;:&lt;br&gt;&#xA;the communication is with who you expect it to be (not a man-in-the-middle).&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For a longer &amp;ldquo;Security Glossary&amp;rdquo;, please see &lt;a href=&#34;https://docs.google.com/document/d/1qs3jEIQvocdVhSxCSPLF1BoLnp91aLnuUIasvl-maYo/edit?usp=sharing&#34; target=&#34;_blank&#34;&gt;this Google&#xA;doc&lt;/a&gt;&#xA;I created.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;hashing-vs-encryption&#34;&gt;Hashing vs Encryption&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In essence:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;hashing&lt;/strong&gt;: provides &lt;em&gt;integrity&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;encryption&lt;/strong&gt;: provides &lt;em&gt;confidentiality&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Often cryptographic primitives need to be combined. For example, &lt;a href=&#34;/posts/security-basics/#public-key-cryptography&#34;&gt;public-key&#xA;cryptography&lt;/a&gt; uses RSA (a slow,&#xA;but very secure algorithm) for &lt;em&gt;communicating&lt;/em&gt; securely, while internally using&#xA;AES (a faster, but less secure algorithm †) for &lt;em&gt;encrypting&lt;/em&gt; data with a shared&#xA;key, while using a hash function for generating a message digest to ensure both&#xA;parties can verify the &lt;em&gt;integrity&lt;/em&gt; of the payload sent/received.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† less secure in the sense that you have to share a secret key with the person&#xA;you wish to communicate with, but that&amp;rsquo;s what public-key cryptography helps to&#xA;secure.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;why-use-a-hash-function&#34;&gt;Why use a hash function?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Hash functions (or more specifically their output: &lt;em&gt;digests&lt;/em&gt;) can be used for&#xA;many things, like indexing data in a hash table, fingerprinting (i.e. detecting&#xA;duplicate data or uniquely identifying files), or as a checksum (i.e. detecting&#xA;data corruption).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Message authentication (i.e. message &lt;em&gt;integrity&lt;/em&gt;) involves hashing the message&#xA;to produce a digest and encrypting the digest with the private key to produce a&#xA;digital signature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to verify this &amp;lsquo;signature&amp;rsquo; the recipient of the encrypted message would&#xA;need to compute a hash of the message, then decrypting the signer&amp;rsquo;s public key&#xA;and comparing the computed digest against the decrypted digest sent within the&#xA;encrypted message.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the digest you generated is the same as the decrypted digest, then we can be&#xA;sure the message was delivered unmodified whilst in transit (e.g.&#xA;&amp;lsquo;man-in-the-middle&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;base64-encoding&#34;&gt;Base64 Encoding&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Base64 is a way of taking binary data and transforming it into a text-based&#xA;format. It is commonly used when there is a need to transfer the binary data&#xA;over a medium that only supports textual data (e.g. you can Base64 encode images&#xA;so they can be inlined into HTML).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How it works: Base64 encoding takes three bytes, each consisting of eight bits,&#xA;and represents them as four printable characters in the ASCII standard.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Base64 encoded strings are NOT secure.&lt;br&gt;&#xA;Remember, it &lt;em&gt;encodes&lt;/em&gt; data, not &lt;em&gt;encrypt&lt;/em&gt; it.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;mac-vs-hmac&#34;&gt;MAC vs HMAC&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &amp;lsquo;MAC&amp;rsquo; (Message Authentication Code) uses symmetrical cryptography with an&#xA;encryption algorithm (such as AES †) to verify the integrity of a message,&#xA;whereas a &amp;lsquo;HMAC&amp;rsquo; will use a hash function (such as SHA256) internally instead of&#xA;an encryption algorithm.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† encryption algorithms: AES (Advanced Encryption Standard), Blowfish, DES&#xA;(Data Encryption Standard), Triple DES, Serpent, and Twofish.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Below is an example HMAC written in &lt;a href=&#34;https://www.gnu.org/software/bash/&#34; target=&#34;_blank&#34;&gt;Bash&lt;/a&gt;&#xA;and using the &lt;a href=&#34;https://www.openssl.org/&#34; target=&#34;_blank&#34;&gt;OpenSSL&lt;/a&gt; command-line tool.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function hmac {&#xA;  digest=&amp;quot;$1&amp;quot;&#xA;  data=&amp;quot;$2&amp;quot;&#xA;  key=&amp;quot;$3&amp;quot;&#xA;  shift 3&#xA;  echo -n &amp;quot;$data&amp;quot; | openssl dgst &amp;quot;-$digest&amp;quot; -hmac &amp;quot;$key&amp;quot; &amp;quot;$@&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The way you would use it is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;hmac sha256 &amp;quot;message to be hashed&amp;quot; secret-key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can swap &lt;code&gt;sha256&lt;/code&gt; for any supported digest algorithm (see &lt;code&gt;openssl dgst -h&lt;/code&gt; for details).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Which would generate the digest output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;44db14fe496c4bc4af5e8e6e3683e5db7acffa555897cf4b2b4345abaaf1ace3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now because the implementation is using the &lt;code&gt;openssl&lt;/code&gt; command, you can also&#xA;choose to convert the hexidecimal output into binary and then Base64 encode that&#xA;binary output, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;hmac sha256 &amp;quot;message to be hashed&amp;quot; secret-key -binary | base64&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;RNsU/klsS8SvXo5uNoPl23rP+lVYl89LK0NFq6rxrOM=&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t have to use an abstraction around the command obviously, you can just&#xA;use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cat plaintext.txt | openssl dgst -sha512 -binary | base64&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;base64&lt;/code&gt; could be replaced with openssl&amp;rsquo;s base64 encoding command:&#xA;&lt;code&gt;openssl enc -base64 -A&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;random-password-generation&#34;&gt;Random Password Generation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Generating random passwords that are complex enough to make automated attacks&#xA;difficult can be a bit tedious, yet important. But if you install a program such&#xA;as &lt;code&gt;pwgen&lt;/code&gt; (&lt;code&gt;brew install pwgen&lt;/code&gt;) you&amp;rsquo;ll be able to generate random and complex&#xA;passwords very easily.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once installed, add the following alias to your shell:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;alias psw=&amp;quot;pwgen -sy 20 1&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now when you execute &lt;code&gt;psw&lt;/code&gt; you&amp;rsquo;ll get output that looks something like the&#xA;following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;|93&amp;lt;3(M;r?~40c$A@&amp;gt;{\&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;hash-functions&#34;&gt;Hash Functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many different ways of accessing a hash function, two options we&amp;rsquo;ll&#xA;look at will be using the executable &lt;code&gt;shasum&lt;/code&gt; (provided by macOS) and the&#xA;&lt;code&gt;hashlib&lt;/code&gt; package provided by the &lt;a href=&#34;https://www.python.org/&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt; programming&#xA;language.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;shasum&#34;&gt;shasum&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s generate a hexidecimal digest of the message &lt;code&gt;foobar&lt;/code&gt; using the SHA512&#xA;hash algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo -n foobar | shasum -a 512&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;code&gt;shasum -h&lt;/code&gt; for all available algorithms.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Which outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0a50261ebd1a390fed2bf326f2673c145582a6342d523204973d0219337f81616a8069b012587cf5&#xA;635f6925f1b56c360230c19b273500ee013e030601bf2425&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;hashlib&#34;&gt;hashlib&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s again generate a hexidecimal digest of the message &lt;code&gt;foobar&lt;/code&gt; using the&#xA;SHA512 hash algorithm, now using Python:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import hashlib&#xA;message = hashlib.sha512()&#xA;message.update(b&amp;quot;foobar&amp;quot;)&#xA;print(message.hexdigest())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which outputs the same digest as the &lt;code&gt;shasum&lt;/code&gt; command produced:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0a50261ebd1a390fed2bf326f2673c145582a6342d523204973d0219337f81616a8069b012587cf5&#xA;635f6925f1b56c360230c19b273500ee013e030601bf2425&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;cksum&#34;&gt;cksum&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Remember hash functions generate a digest of some message input, and one such&#xA;use of that digest output is data corruption (i.e. a checksum).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The macOS also provides a &lt;code&gt;cksum&lt;/code&gt; command which let&amp;rsquo;s you generate a checksum,&#xA;like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo foobar | cksum&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;857691210 7&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first number is the checksum and the second number is the amount of data in&#xA;bytes.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;openssh&#34;&gt;OpenSSH&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OpenSSH provides secure and encrypted tunneling capabilities and is typically&#xA;used to enable secure shell connections from your machine to external servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to generate a cryptographically secure key pair, execute the following&#xA;command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C &amp;quot;your.email@domain.com&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This uses the RSA algorithm (which is the default, so the &lt;code&gt;-t&lt;/code&gt; can be omitted)&#xA;along with a key size of 4096 bits (the default is 2048).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The output of this command will be a public and private key pair.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s usually best to generate these keys (or at least move them when generated)&#xA;within the &lt;code&gt;~/.ssh&lt;/code&gt; directory.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;ssh-agent&#34;&gt;SSH Agent&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One thing that catches me out all the time is when I open a new terminal tab or&#xA;shell instance and I go to push up some code changes to a remote server only to&#xA;discover an error saying I&amp;rsquo;m not authenticated. This is because the new&#xA;terminal/shell instance doesn&amp;rsquo;t have the SSH agent running which is what makes&#xA;my SSH key pair available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This happens so often I&amp;rsquo;ve created an alias to make starting up the SSH agent&#xA;and loading my SSH private key very quick and easy:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;alias sshagent=&#39;eval &amp;quot;$(ssh-agent -s)&amp;quot; &amp;amp;&amp;amp; ssh-add -K ~/.ssh/github_rsa&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the use of the &lt;code&gt;-K&lt;/code&gt; flag is macOS specific, it means it&amp;rsquo;ll add the key&#xA;into the macOS keychain program.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;openssl&#34;&gt;OpenSSL&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OpenSSL is designed to provide a method for securing web based communication&#xA;(think HTTPS/TLS/SSL).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for a full list of commands see: &lt;code&gt;openssl -h&lt;/code&gt; and &lt;code&gt;openssl &amp;lt;command&amp;gt; -h&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;key-exchanges&#34;&gt;Key Exchanges&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two popular key exchange algorithms:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;RSA&lt;/li&gt;&#xA;&lt;li&gt;Diffie-Hellman&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;For the specific details of each I recommend you read &lt;a href=&#34;https://technet.microsoft.com/en-us/library/cc962035.aspx&#34; target=&#34;_blank&#34;&gt;this post on the&#xA;differences&lt;/a&gt;. In&#xA;short RSA uses the person&amp;rsquo;s public key to encrypt the secret, while&#xA;Diffie-Hellman uses a mathematical function to ensure only those two people&#xA;communicating can calculate the secret based on the information that&amp;rsquo;s publicly&#xA;available.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generating-a-key-pair&#34;&gt;Generating a key pair&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to generate a RSA based public/private key pair, execute the following&#xA;commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# generate a private key&#xA;openssl genrsa -out private_key.pem 4096&#xA;&#xA;# generate a public key, from the private key&#xA;openssl rsa -pubout -in private_key.pem -out public_key.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;encrypting-and-decrypting&#34;&gt;Encrypting and Decrypting&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following examples use symmetric encryption, and so you&amp;rsquo;ll be asked for a&#xA;secret key when encrypting and decrypting (although you could also use the&#xA;&lt;code&gt;-pass&lt;/code&gt; flag like so &lt;code&gt;-pass pass:&amp;lt;your_password&amp;gt;&lt;/code&gt;, yeah the syntax is odd and&#xA;it&amp;rsquo;s the same for decrypting):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# symmetric encryption (you&#39;ll be asked for a key)&#xA;echo foobar | openssl enc -aes-256-cbc -out message.enc&#xA;&#xA;# decrypt that encrypted message&#xA;openssl enc -aes-256-cbc -in message.enc -d&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;.enc&lt;/code&gt; is a commonly used format to indicate a file is encrypted (&lt;code&gt;.asc&lt;/code&gt;&#xA;is specifically used for asymmetric encryption).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m passing in the message via stdin (when encrypting), but specifying a file&#xA;for the output (when decrypting), but you could use a file for both by&#xA;explicitly specifying the &lt;code&gt;-in&lt;/code&gt; and &lt;code&gt;-out&lt;/code&gt; flags to provide a text file instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Annoyingly with &lt;code&gt;openssl&lt;/code&gt; the same thing can be done a million different ways,&#xA;so (for example) you might also find that you can do the above &lt;em&gt;without&lt;/em&gt; the&#xA;&lt;code&gt;enc&lt;/code&gt; portion of the command (and thus removing the &lt;code&gt;-&lt;/code&gt; prefix from the selected&#xA;algorithm):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# symmetric encryption&#xA;echo foobar | openssl aes-256-cbc -out message.enc&#xA;&#xA;# decrypt that encrypted message&#xA;openssl aes-256-cbc -in message.enc -d&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;encoding&#34;&gt;Encoding&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;You can also generate Base64 output of the encrypted data, by using the &lt;code&gt;-a&lt;/code&gt;&#xA;flag like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ echo foobar | openssl aes-256-cbc -a&#xA;&#xA;U2FsdGVkX19/L0WtkvCNlpMiQnvD1SWGM19lm4m6xK4=&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;code&gt;man enc&lt;/code&gt; for details&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;salts&#34;&gt;Salts&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also worth mentioning that the default behaviour for OpenSSL is to use a&#xA;&amp;lsquo;salt&amp;rsquo; when using encrypting the message. A salt is random data appended to your&#xA;already hashed message and then that is hashed itself. In pseudo-code it would&#xA;look like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$pwd = hash(hash($password) + salt)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You would then store the value of &lt;code&gt;$pwd&lt;/code&gt; in your database along with the salt&#xA;itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The security doesn&amp;rsquo;t come from obfuscating the salt, but more that a rainbow&#xA;table attack can&amp;rsquo;t now automatically loop/check its collection of hashed&#xA;passwords. An attacker would need to incorporate your (per-user) unique salt&#xA;value into their check against a predetermined list of hashes, and they also&#xA;wouldn&amp;rsquo;t know if the salt was prefixed or suffixed to the password itself.&#xA;Making it computationally very expensive and time consuming to attempt.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also see that a salt is used by trying to read an encrypted file (&lt;code&gt;cat message.enc&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Salted__MJin¨MàÍ£?è,random¡:~randomW!5µõ&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;asymmetrical-encryption&#34;&gt;Asymmetrical Encryption&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;If you need to you can use a public key to encrypt data with (i.e. asymmetrical&#xA;encryption) by utilising the &lt;code&gt;openssl rsautl&lt;/code&gt; command, which stands for &amp;ldquo;RSA&#xA;Utility&amp;rdquo; and is commonly used to sign, verify, encrypt and decrypt data using&#xA;the RSA algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example we have a file &lt;code&gt;plaintext.txt&lt;/code&gt; we encrypt using a&#xA;public key. It will now only be possible to decrypt the &lt;code&gt;secret.enc&lt;/code&gt; file if you&#xA;have the corresponding private key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# encrypting&#xA;openssl rsautl -encrypt -pubin -inkey public_key.pem -in plaintext.txt -out secret.enc&#xA;&#xA;# decrypting&#xA;openssl rsautl -decrypt -inkey private_key.pem -in secret.enc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;randomness&#34;&gt;Randomness&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OpenSSL also offers a way to generate random binary data which you can then&#xA;export as either hexidecimal or base64 formats:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the following examples, &lt;code&gt;64&lt;/code&gt; is the number of bytes to be generated.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ openssl rand 64&#xA;&#xA;RR_wK[=q5}VrdMܾj{8(Ty]7;file://Integralist-MBPr/tmp&#xA;&#xA;$ openssl rand 64 -hex&#xA;&#xA;660baf33c189ced722a07c6a29d35a7e4584bb954c8c86f2cfd4ea8d892bff32fc188b0c56cbe0a5&#xA;6d60b628cdee697308b0cf3806cd95052b743bec5ccc5240&#xA;&#xA;$ openssl rand 64 -base64&#xA;&#xA;JIPU5SiCgKP3XVrnef1gY+PxjBvjdQgSN+OJoBAdWmCa/cRvDdFl01GQiSwFimQ5&#xA;1lVa/7hfYIK6Z5jjHNauaQ==&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;gpg&#34;&gt;GPG&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;GPG is a tool which provides encryption and signing capabilities, and supports&#xA;both symmetrical and asymmetrical encryption + digital signing of your encrypted&#xA;content to ensure the integrity.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generating-a-key-pair-1&#34;&gt;Generating a key pair&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To generate a new GPG key pair you would execute the following command and&#xA;interactively fill in the details:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --gen-key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;automate&#34;&gt;Automate&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you prefer to automate this you can create a file to contain the details and&#xA;pass that into the command-line instead. The following code generates a new&#xA;&lt;code&gt;batch_file&lt;/code&gt; that will contain the information we would otherwise have to enter&#xA;manually:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ cat &amp;gt; batch_file &amp;lt;&amp;lt;EOF&#xA;     %echo Generating a basic OpenPGP key&#xA;     Key-Type: RSA&#xA;     Key-Length: 4096&#xA;     Subkey-Type: Default&#xA;     Name-Real: Your Name&#xA;     Name-Comment: Integralist testing&#xA;     Name-Email: foo@example.com&#xA;     Expire-Date: 0&#xA;     Passphrase: foobar&#xA;     %commit&#xA;     %echo done&#xA;EOF&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we have this file we can pass it along with the &lt;code&gt;--gen-key&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gpg --gen-key --batch batch_file&#xA;&#xA;gpg: Generating a basic OpenPGP key&#xA;gpg: key 4BCAEAAD199B5FE8 marked as ultimately trusted&#xA;gpg: directory &#39;/Users/Integralist/.gnupg/openpgp-revocs.d&#39; created&#xA;gpg: revocation certificate stored as &#39;/Users/Integralist/.gnupg/openpgp-revocs.d/\&#xA;  CFE96536285D83C990567BF64BCAEAAD199B5FE8.rev&#39;&#xA;gpg: done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if we check our list of keys we&amp;rsquo;ll see the new one we just generated:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gpg --list-keys&#xA;&#xA;/Users/Integralist/.gnupg/pubring.gpg&#xA;---------------------------------------&#xA;pub   rsa4096 2018-02-17 [SCEA]&#xA;      CFE96536285D83C990567BF64BCAEAAD199B5FE8&#xA;uid           [ultimate] Your Name (Integralist testing) &amp;lt;foo@example.com&amp;gt;&#xA;sub   rsa2048 2018-02-17 [E]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;revocation&#34;&gt;Revocation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When you generate a new key pair, if you intend on publishing your public key&#xA;online, then you&amp;rsquo;ll want to generate a revocation certificate. Doing this will&#xA;mean you can revoke your original key pair if your private key becomes&#xA;compromised (or you just want to decommission it):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --gen-revoke your.email@domain.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When you&amp;rsquo;re ready to decommission it, just import the certifcate into your&#xA;keyring:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --import revocation.cert&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then also push up your key identifier to a key server to force it to&#xA;recognise the key has been revoked:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --keyserver pgp.mit.edu --send-keys &amp;lt;key_id&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;asymmetrical-encryption-and-decryption&#34;&gt;Asymmetrical Encryption and Decryption&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to encrypt some data using someone elses public key (i.e. so only they&#xA;can decrypt the data) you first need access to their public key and have it&#xA;imported to your gpg keyring:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --import public.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to verify the integrity of the public key you have acquired, then&#xA;you should speak securely with the recipient who owns the public key and ask&#xA;them to give you their digital &amp;lsquo;fingerprint&amp;rsquo;. You can then verify it matches&#xA;what you have using the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --fingerprint &amp;lt;pub_key_id&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll then look for the fingerprint in the gpg output. The fingerprint should&#xA;look something like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FDFB E9B5 24BA 6972 A3AA 44B9 A1B1 7E6F DD86 E7F5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The command for encrypting a file &lt;code&gt;plaintext.txt&lt;/code&gt; using their public key would&#xA;be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --encrypt -u &amp;quot;Sender User Name&amp;quot; -r &amp;quot;Receiver User Name&amp;quot; plaintext.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you&amp;rsquo;ve encrypted the file using that person&amp;rsquo;s public key, it means they can&#xA;decrypt the file simply with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg -d plaintext.txt.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;symmetrical-encryption-and-decryption&#34;&gt;Symmetrical Encryption and Decryption&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;By default gpg uses the AES algorithm for its symmetrical encryption. The&#xA;command to use is (you&amp;rsquo;ll be asked to provide a passphrase):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --symmetric plaintext.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can specify a different algorithm, as the default isn&amp;rsquo;t as secure as it&#xA;could be. Let&amp;rsquo;s use a 256bit encryption key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --symmetric --cipher-algo AES256 plaintext.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;code&gt;gpg --version&lt;/code&gt; for all available ciphers&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;signing-keys&#34;&gt;Signing keys&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you want to explicitly trust a public key you have imported, you can &amp;lsquo;sign&amp;rsquo;&#xA;it. You do this using the &lt;code&gt;--sign-key&lt;/code&gt; flag. Doing this can also be beneficial&#xA;for the owner of that public key (Bob), because if a friend of yours (Alice)&#xA;trusts &lt;em&gt;you&lt;/em&gt; and they see you&amp;rsquo;ve signed Bob&amp;rsquo;s public key, then Alice is more&#xA;likely to trust Bob as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for Bob to benefit from this &amp;lsquo;web of trust&amp;rsquo; you need to send him back&#xA;his public key which you signed. Bob would need to import that version of his&#xA;public key back into his gpg keyring, so that he can then republish it online&#xA;for others to see the &lt;em&gt;you&lt;/em&gt; trust him.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how you would export Bob&amp;rsquo;s public key, which&#xA;you previously imported and signed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --export --armor bob@example.org&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;--armor&lt;/code&gt; simply outputs the binary data as ASCII&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;signing-encrypted-files&#34;&gt;Signing encrypted files&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It can be useful to sign a file that you encrypt, so that the person who will&#xA;decrypt the file can verify it was you who sent it to them, and also check that&#xA;the integrity of the file is still intact.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this provides a combination of &lt;em&gt;authenticity&lt;/em&gt; and &lt;em&gt;integrity&lt;/em&gt; (as&#xA;defined within the &lt;a href=&#34;#1&#34;&gt;terminology section&lt;/a&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You do this by using the &lt;code&gt;--sign&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --local-user Bob --encrypt --recipient Alice --sign plaintext.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m using &lt;code&gt;--local-user&lt;/code&gt; because I have many different key pairs setup&#xA;for testing.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This will generate a &lt;code&gt;plaintext.txt.gpg&lt;/code&gt; encrypted file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The recipient (Alice), can either decrypt the file using Bob&amp;rsquo;s public key and&#xA;this will both decrypt and verify the signature, or Alice could just use the&#xA;&lt;code&gt;--verify&lt;/code&gt; flag if she didn&amp;rsquo;t want to decrypt the file.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gpg --verify plaintext.txt.gpg&#xA;&#xA;gpg: Signature made Mon Feb 19 10:16:38 2018 GMT&#xA;gpg:                using RSA key F2G91BE243E405E5B64B08A1CB5EBDB2561C861B&#xA;gpg: Good signature from &amp;quot;Bob &amp;lt;bob@example.com&amp;gt;&amp;quot; [ultimate]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;keybase&#34;&gt;Keybase&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://keybase.io/&#34; target=&#34;_blank&#34;&gt;Keybase&lt;/a&gt; is a public-key directory that maps social media&#xA;identities to encryption keys in a publicly auditable manner. Keybase offers an&#xA;end-to-end encrypted chat and cloud storage system, called Keybase Chat and the&#xA;Keybase filesystem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to use the command-line tool &lt;code&gt;keybase&lt;/code&gt; you&amp;rsquo;ll need to register for an&#xA;account on their website.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To install keybase on macOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install keybase&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once installed you&amp;rsquo;ll need to login:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase login&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point you can either generate a fresh key pair or select an existing gpg&#xA;key pair:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# generate new key pair&#xA;keybase pgp gen&#xA;&#xA;# select existing key pair&#xA;keybase pgp select&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can search for other keybase users:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase search sthulb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then encrypt data for another keybase user, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase encrypt -i info.txt -o info.txt.asc sthulb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you receive an encrypted file you can decrypt it, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase decrypt -i info.txt.asc -o info.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you receive an encrypted file (&lt;code&gt;info.txt.gpg&lt;/code&gt;) using your keybase pub key but&#xA;the senders &lt;em&gt;not&lt;/em&gt; using keybase (e.g. they&amp;rsquo;ve encrypted the file using their own&#xA;gpg private key), then you&amp;rsquo;ll need to have their public key in your gpg keyring:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase pgp decrypt -i info.txt.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/hashing-encryption-encoding/</guid>
      <link>https://www.integralist.co.uk/posts/hashing-encryption-encoding/</link>
      <pubDate>Fri, 16 Feb 2018 00:00:00 +0000</pubDate>
      <title>Hashing, Encryption and Encoding</title>
    </item>
    <item>
      <description>&lt;p&gt;Before we get started, here&amp;rsquo;s a diagram to give you an overview of what we will&#xA;be covering in this post:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/terminals-kernals-shells.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/terminals-kernals-shells.png&#34; alt=&#34;terminals kernals shells&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing I want to clarify in the above image is that each box is &lt;em&gt;within&lt;/em&gt; the&#xA;parent box. So for example, The &amp;ldquo;Program: terminal&amp;rdquo; is interacting with a&#xA;contained shell, while the shell then spawns either a &amp;ldquo;Built-in&amp;rdquo; or &amp;ldquo;Program&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Nearly four years after this post was published someone else&#xA;published &lt;a href=&#34;https://www.poor.dev/blog/terminal-anatomy/&#34; target=&#34;_blank&#34;&gt;https://www.poor.dev/blog/terminal-anatomy/&lt;/a&gt; which is an excellent&#xA;write up that provides a really good animation of how the terminal interacts&#xA;with the shell, and it goes into much deeper explanation that I do here. So I&#xA;recommend reading that also.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;kernel&#34;&gt;Kernel&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A computer has a kernel.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The kernel is responsible for managing the computer&amp;rsquo;s system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The kernel has no user interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To interact with the kernel you use an intermediary &amp;ldquo;program&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;program&#34;&gt;Program&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &amp;ldquo;&lt;a href=&#34;https://simple.wikipedia.org/wiki/Computer_program&#34; target=&#34;_blank&#34;&gt;program&lt;/a&gt;&amp;rdquo; is a&#xA;structured collection of instructions (machine code) that a computer can&#xA;execute.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Your computer has many programs. One such example would be the &amp;lsquo;terminal&#xA;emulator&amp;rsquo; program.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see next section for explanation of what a &amp;ldquo;terminal&amp;rdquo; is.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Depending on the programming language used to create the program, either the&#xA;program is &lt;em&gt;compiled&lt;/em&gt; down into binary so it can be understood by the computer,&#xA;or it&amp;rsquo;ll be &lt;em&gt;interpreted&lt;/em&gt; by another program that then generates machine code&#xA;out of the human readable program.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;executables&#34;&gt;Executables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Executables (or &amp;lsquo;executable binaries&amp;rsquo;) are programs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;More specifically, an &amp;lsquo;executable&amp;rsquo; is a file that &lt;em&gt;contains&lt;/em&gt; a program.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;these are also often referred to as just &amp;lsquo;binaries&amp;rsquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Executables are generally the &lt;em&gt;result&lt;/em&gt; of a program being turned into something&#xA;that can be &amp;lsquo;executed&amp;rsquo; by the computer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Executables can be found in multiple locations, e.g. look at the &lt;code&gt;$PATH&lt;/code&gt;&#xA;environment variable in a terminal.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ echo $PATH&#xA;&#xA;/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;separate the output by &lt;code&gt;:&lt;/code&gt; and you see there are six directories&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;terminal&#34;&gt;Terminal&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A terminal is an input/output device.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Traditionally terminals would have been a &lt;em&gt;real&lt;/em&gt; &amp;lsquo;hardware&amp;rsquo; device that you used&#xA;to interact with a computer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. the computer would be a large box in a server room, and the terminal would&#xA;be a monitor/keyboard connected to the computer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In modern computing we have &lt;em&gt;electronic&lt;/em&gt; terminals.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The modern equivalent of a terminal is known as a &amp;lsquo;terminal emulator&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Terminal emulators ironically (or confusingly) are part of the computer they&#xA;would have previously been plugged into separately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to use a GUI (graphical user interface) to interact with your&#xA;computer, you can use a terminal emulator.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;shell&#34;&gt;Shell&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A shell is a program which is accessed &lt;em&gt;via&lt;/em&gt; a terminal emulator.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The terminal accepts input, passes it to the shell, and the shell&amp;rsquo;s output is&#xA;sent back to the terminal to be displayed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The shell accepts input as a set of commands.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The available commands vary depending on the shell (e.g. different shells have&#xA;different commands).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to fulfil your instructions, commands are interpreted by the shell and&#xA;the shell determines if it should either:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;load &lt;em&gt;another&lt;/em&gt; program&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;or&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;execute a &amp;lsquo;builtin&amp;rsquo; function&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;shell-builtins&#34;&gt;Shell Builtins&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A &amp;lsquo;builtin&amp;rsquo; function is one that is provided by the shell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a command is provided and the shell has no corresponding builtin associated&#xA;with the given command, it will lookup the command via a separate list of&#xA;available &lt;em&gt;external&lt;/em&gt; &amp;lsquo;executables&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A builtin command can affect the internal state of the shell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why a command such as &lt;code&gt;cd&lt;/code&gt; &lt;em&gt;must&lt;/em&gt; be part of the shell (i.e. a builtin),&#xA;because an external program can&amp;rsquo;t change the current directory of the shell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other commands, like &lt;code&gt;echo&lt;/code&gt;, might be (and are in this case) built into the&#xA;shell for the sake of performance (it&amp;rsquo;s quicker to call the builtin &lt;code&gt;echo&lt;/code&gt; than&#xA;it is to load and manage the external executable &lt;code&gt;echo&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;documentation&#34;&gt;Documentation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most people are aware of &amp;lsquo;&lt;a href=&#34;/posts/man-pages/&#34;&gt;manuals&lt;/a&gt;&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. &lt;code&gt;man bash&lt;/code&gt; returns the documentation for the Bash shell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Manuals do not cover shell builtins.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;exit&lt;/code&gt; command is a shell builtin, so what happens when looking up a manual&#xA;for it?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. &lt;code&gt;man exit&lt;/code&gt; returns a generic &amp;lsquo;BUILTIN&amp;rsquo; documentation page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you see that page, then you know the command is a shell builtin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another way to tell if a command is a builtin vs an executable is to use the&#xA;&lt;code&gt;type&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type exit&#xA;&#xA;exit is a shell builtin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One other reason I like to use &lt;code&gt;type&lt;/code&gt; is when trying to figure out what a shell&#xA;alias is set to (in case you&amp;rsquo;re unfamiliar, in most shells you can assign a long&#xA;or hard to remember command to a short variable name). Imagine I&amp;rsquo;ve created an&#xA;alias like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;alias gb=&amp;quot;git branch --list &#39;integralist*&#39;&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I can find out later what I assigned to the alias using the &lt;code&gt;type&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type gb&#xA;&#xA;gb is aliased to `git branch --list &#39;integralist*&#39;&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To read the documentation for a builtin, you need to use the &lt;code&gt;help&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ help exit&#xA;&#xA;exit: exit [n]&#xA;    Exit the shell.&#xA;&#xA;    Exits the shell with a status of N.  If N is omitted, the exit status&#xA;    is that of the last command executed.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;help&lt;/code&gt; command is itself a builtin (hence it knows about builtins, unlike&#xA;&lt;code&gt;man&lt;/code&gt; which isn&amp;rsquo;t a builtin).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type help&#xA;&#xA;help is a shell builtin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can use the &lt;code&gt;help&lt;/code&gt; command to read its documentation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ help help&#xA;&#xA;help: help [-dms] [pattern ...]&#xA;    Display information about builtin commands.&#xA;&#xA;    Displays brief summaries of builtin commands.  If PATTERN is&#xA;    specified, gives detailed help on all commands matching PATTERN,&#xA;    otherwise the list of help topics is printed.&#xA;&#xA;    Options:&#xA;      -d        output short description for each topic&#xA;      -m        display usage in pseudo-manpage format&#xA;      -s        output only a short usage synopsis for each topic matching&#xA;                PATTERN&#xA;&#xA;    Arguments:&#xA;      PATTERN   Pattern specifying a help topic&#xA;&#xA;    Exit Status:&#xA;    Returns success unless PATTERN is not found or an invalid option is given.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you run the &lt;code&gt;help&lt;/code&gt; command by itself you&amp;rsquo;ll see a list of commands that can&#xA;be passed to &lt;code&gt;help&lt;/code&gt; (you&amp;rsquo;ll see in the list &lt;code&gt;exit&lt;/code&gt;, hence why we could run &lt;code&gt;help exit&lt;/code&gt; earlier):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ help&#xA;&#xA;GNU bash, version 5.0.18(1)-release (x86_64-apple-darwin19.5.0)&#xA;These shell commands are defined internally.  Type `help&#39; to see this list.&#xA;Type `help name&#39; to find out more about the function `name&#39;.&#xA;Use `info bash&#39; to find out more about the shell in general.&#xA;Use `man -k&#39; or `info&#39; to find out more about commands not in this list.&#xA;&#xA;A star (*) next to a name means that the command is disabled.&#xA;&#xA; job_spec [&amp;amp;]                                                                                                           &#xA; (( expression ))                                                                                                       &#xA; . filename [arguments]                                                                                                 &#xA; :                                                                                                                      &#xA; [ arg... ]                                                                                                             &#xA; [[ expression ]]                                                                                                       &#xA; alias [-p] [name[=value] ... ]                                                                                         &#xA; bg [job_spec ...]                                                                                                      &#xA; bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] \&#xA; [-x keyseq:shell-command] [keyseq:readlin&amp;gt;  &#xA; break [n]                                                                                                              &#xA; builtin [shell-builtin [arg ...]]                                                                                      &#xA; caller [expr]                                                                                                          &#xA; case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac                                                             &#xA; cd [-L|[-P [-e]] [-@]] [dir]                                                                                           &#xA; command [-pVv] command [arg ...]                                                                                       &#xA; compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist]  \&#xA; [-F function] [-C command] [-X filterpat&amp;gt;  &#xA; complete [-abcdefgjksuv] [-pr] [-DEI] [-o option] [-A action] [-G globpat] \&#xA; [-W wordlist]  [-F function] [-C command]&amp;gt;  &#xA; compopt [-o|+o option] [-DEI] [name ...]                                                                               &#xA; continue [n]                                                                                                           &#xA; coproc [NAME] command [redirections]                                                                                   &#xA; declare [-aAfFgilnrtux] [-p] [name[=value] ...]                                                                        &#xA; dirs [-clpv] [+N] [-N]                                                                                                 &#xA; disown [-h] [-ar] [jobspec ... | pid ...]                                                                              &#xA; echo [-neE] [arg ...]                                                                                                  &#xA; enable [-a] [-dnps] [-f filename] [name ...]                                                                           &#xA; eval [arg ...]                                                                                                         &#xA; exec [-cl] [-a name] [command [arguments ...]] [redirection ...]                                                       &#xA; exit [n]                                                                                                               &#xA; export [-fn] [name[=value] ...] or export -p                                                                           &#xA; false                                                                                                                  &#xA; fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]                                                       &#xA; fg [job_spec]                                                                                                          &#xA; for NAME [in WORDS ... ] ; do COMMANDS; done                                                                           &#xA; for (( exp1; exp2; exp3 )); do COMMANDS; done                                                                          &#xA; function name { COMMANDS ; } or name () { COMMANDS ; }                                                                 &#xA; getopts optstring name [arg]                                                                                           &#xA; hash [-lr] [-p pathname] [-dt] [name ...]                                                                              &#xA; help [-dms] [pattern ...]                                                                                              &#xA; history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]&#xA; if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi&#xA; jobs [-lnprs] [jobspec ...] or jobs -x command [args]&#xA; kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]&#xA; let arg [arg ...]&#xA; local [option] name[=value] ...&#xA; logout [n]&#xA; mapfile [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] \&#xA; [-c quantum] [array]&#xA; popd [-n] [+N | -N]&#xA; printf [-v var] format [arguments]&#xA; pushd [-n] [+N | -N | dir]&#xA; pwd [-LP]&#xA; read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] \&#xA; [-t timeout] [-u fd] [name ...]&#xA; readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] \&#xA; [-c quantum] [array]&#xA; readonly [-aAf] [name[=value] ...] or readonly -p&#xA; return [n]&#xA; select NAME [in WORDS ... ;] do COMMANDS; done&#xA; set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]&#xA; shift [n]&#xA; shopt [-pqsu] [-o] [optname ...]&#xA; source filename [arguments]&#xA; suspend [-f]&#xA; test [expr]&#xA; time [-p] pipeline&#xA; times&#xA; trap [-lp] [[arg] signal_spec ...]&#xA; true&#xA; type [-afptP] name [name ...]&#xA; typeset [-aAfFgilnrtux] [-p] name[=value] ...&#xA; ulimit [-SHabcdefiklmnpqrstuvxPT] [limit]&#xA; umask [-p] [-S] [mode]&#xA; unalias [-a] name [name ...]&#xA; unset [-f] [-v] [-n] [name ...]&#xA; until COMMANDS; do COMMANDS; done&#xA; variables - Names and meanings of some shell variables&#xA; wait [-fn] [id ...]&#xA; while COMMANDS; do COMMANDS; done&#xA; { COMMANDS ; }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we want to see the documentation for the &lt;code&gt;type&lt;/code&gt; builtin, use &lt;code&gt;help type&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ help type&#xA;&#xA;type: type [-afptP] name [name ...]&#xA;    Display information about command type.&#xA;&#xA;    For each NAME, indicate how it would be interpreted if used as a&#xA;    command name.&#xA;&#xA;    Options:&#xA;      -a        display all locations containing an executable named NAME;&#xA;                includes aliases, builtins, and functions, if and only if&#xA;                the `-p&#39; option is not also used&#xA;      -f        suppress shell function lookup&#xA;      -P        force a PATH search for each NAME, even if it is an alias,&#xA;                builtin, or function, and returns the name of the disk file&#xA;                that would be executed&#xA;      -p        returns either the name of the disk file that would be executed,&#xA;                or nothing if `type -t NAME&#39; would not return `file&#39;&#xA;      -t        output a single word which is one of `alias&#39;, `keyword&#39;,&#xA;                `function&#39;, `builtin&#39;, `file&#39; or `&#39;, if NAME is an alias,&#xA;                shell reserved word, shell function, shell builtin, disk file,&#xA;                or not found, respectively&#xA;&#xA;    Arguments:&#xA;      NAME      Command name to be interpreted.&#xA;&#xA;    Exit Status:&#xA;    Returns success if all of the NAMEs are found; fails if any are not found.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;explicit-requests&#34;&gt;Explicit Requests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When we used the &lt;code&gt;type&lt;/code&gt; command earlier on the &lt;code&gt;exit&lt;/code&gt; command it returned a&#xA;single response (&lt;code&gt;exit is a shell builtin&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s try again with a different command (&lt;code&gt;echo&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type echo&#xA;&#xA;echo is a shell builtin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But if we also apply the &lt;code&gt;-a&lt;/code&gt; flag we get &lt;em&gt;more&lt;/em&gt; output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type -a echo&#xA;&#xA;echo is a shell builtin&#xA;echo is /bin/echo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This indicates that the shell found a builtin first, but that there was &lt;em&gt;also&lt;/em&gt;&#xA;an external executable called &lt;code&gt;echo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you were to execute &lt;code&gt;echo foo&lt;/code&gt; you would be calling the builtin &lt;code&gt;echo&lt;/code&gt;&#xA;command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You could be explicit by executing it via the &lt;code&gt;builtin&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ builtin echo foo&#xA;&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You could also explicitly request the executable and not the builtin by using&#xA;the &lt;code&gt;command&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ command echo foo&#xA;&#xA;foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;locating-programs&#34;&gt;Locating programs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To locate a program you use the &lt;code&gt;which&lt;/code&gt; executable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We know it&amp;rsquo;s an executable by using the &lt;code&gt;type&lt;/code&gt; builtin to check it against:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ type -a which&#xA;&#xA;which is /usr/bin/which&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we use &lt;code&gt;which&lt;/code&gt; to lookup the location of the &lt;code&gt;echo&lt;/code&gt; command, will it find the&#xA;builtin or the external executable?&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ which echo&#xA;&#xA;/bin/echo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see it only found the external executable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;which&lt;/code&gt; command &lt;em&gt;isn&amp;rsquo;t&lt;/em&gt; a builtin, and so it has no idea of where to look&#xA;for builtins.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because, by nature, builtins are built &lt;em&gt;into&lt;/em&gt; the shell itself.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;hashed-types&#34;&gt;Hashed Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you open a fresh terminal screen and execute &lt;code&gt;type man&lt;/code&gt; you would see the&#xA;response &lt;code&gt;man is /usr/bin/man&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you now execute the &lt;code&gt;man&lt;/code&gt; command (e.g. &lt;code&gt;man echo&lt;/code&gt;) and try &lt;code&gt;type man&lt;/code&gt; again&#xA;you&amp;rsquo;ll see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man is hashed (/usr/bin/man)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason for this is because in order for the shell to locate the executable&#xA;it needs to look it up from various locations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These locations are defined in the &lt;code&gt;$PATH&lt;/code&gt; (as we saw earlier).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid having to do that lookup every time, it caches the result in a hash&#xA;table.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we read the Bash manual (&lt;code&gt;man bash&lt;/code&gt;) you&amp;rsquo;ll see the following comment:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Bash uses a hash table to remember the full pathnames of executable files &#xA;(see hash under SHELL BUILTIN COMMANDS below). &#xA;&#xA;A full search of the directories in PATH is performed only if the command is not found in the hash table.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So it seems there is a &lt;code&gt;hash&lt;/code&gt; builtin command, let&amp;rsquo;s take a look at that:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ help hash&#xA;&#xA;hash: hash [-lr] [-p pathname] [-dt] [name ...]&#xA;    Remember or display program locations.&#xA;    &#xA;    Determine and remember the full pathname of each command NAME.  If&#xA;    no arguments are given, information about remembered commands is displayed.&#xA;    &#xA;    Options:&#xA;      -d    forget the remembered location of each NAME&#xA;      -l    display in a format that may be reused as input&#xA;      -p pathname    use PATHNAME as the full pathname of NAME&#xA;      -r    forget all remembered locations&#xA;      -t    print the remembered location of each NAME, preceding&#xA;            each location with the corresponding NAME if multiple&#xA;            NAMEs are given&#xA;    Arguments:&#xA;      NAME    Each NAME is searched for in $PATH and added to the list&#xA;            of remembered commands.&#xA;    &#xA;    Exit Status:&#xA;    Returns success unless NAME is not found or an invalid option is given.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So the documentation informs us of how we can look inside of the shell&amp;rsquo;s hash&#xA;table by using the &lt;code&gt;-l&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ hash -l&#xA;&#xA;builtin hash -p /usr/bin/which which&#xA;builtin hash -p /usr/bin/man man&#xA;builtin hash -p /usr/bin/clear clear&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From this you can see I&amp;rsquo;ve already executed the &lt;code&gt;which&lt;/code&gt;, &lt;code&gt;man&lt;/code&gt; and &lt;code&gt;clear&lt;/code&gt;&#xA;executables, hence they&amp;rsquo;re now cached.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also in the Bash manual is the following comment:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;BASH_CMDS&#xA;    An associative array variable whose members correspond to the internal &#xA;    hash table of commands as maintained by the hash builtin.&#xA;    Elements added to this array appear in the hash table; &#xA;    however, unsetting array elements currently does not cause command names to &#xA;    be removed from the hash table.  &#xA;    If BASH_CMDS is unset, it loses its special properties, even if it is subsequently reset.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This informs us that there is another way to view the hash table contents.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case we can view the internal array the &lt;code&gt;hash&lt;/code&gt; builtin appends to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ declare -p BASH_CMDS&#xA;&#xA;declare -A BASH_CMDS=([which]=&amp;quot;/usr/bin/which&amp;quot; [man]=&amp;quot;/usr/bin/man&amp;quot; [clear]=&amp;quot;/usr/bin/clear&amp;quot; )&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s not as clear to read as the &lt;code&gt;hash&lt;/code&gt; output, but this is probably&#xA;more useful for interacting with programatically.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;list-of-all-builtins-vs-executables&#34;&gt;List of all builtins vs executables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For a list of builtins you can use (in the Bash shell at least):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ enable -a&#xA;&#xA;enable .&#xA;enable :&#xA;enable [&#xA;enable alias&#xA;enable bg&#xA;enable bind&#xA;enable break&#xA;enable builtin&#xA;enable caller&#xA;enable cd&#xA;enable command&#xA;enable compgen&#xA;enable complete&#xA;enable compopt&#xA;enable continue&#xA;enable declare&#xA;enable dirs&#xA;enable disown&#xA;enable echo&#xA;enable enable&#xA;enable eval&#xA;enable exec&#xA;enable exit&#xA;enable export&#xA;enable false&#xA;enable fc&#xA;enable fg&#xA;enable getopts&#xA;enable hash&#xA;enable help&#xA;enable history&#xA;enable jobs&#xA;enable kill&#xA;enable let&#xA;enable local&#xA;enable logout&#xA;enable mapfile&#xA;enable popd&#xA;enable printf&#xA;enable pushd&#xA;enable pwd&#xA;enable read&#xA;enable readarray&#xA;enable readonly&#xA;enable return&#xA;enable set&#xA;enable shift&#xA;enable shopt&#xA;enable source&#xA;enable suspend&#xA;enable test&#xA;enable times&#xA;enable trap&#xA;enable true&#xA;enable type&#xA;enable typeset&#xA;enable ulimit&#xA;enable umask&#xA;enable unalias&#xA;enable unset&#xA;enable wait&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;an online reference can be found&#xA;&lt;a href=&#34;https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#Bash-Builtins&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To list out all available executables is a little more tricky.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First you need to access only those directories you&amp;rsquo;re interested in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ echo $PATH | tr &#39;:&#39; &#39;\n&#39; | sort | egrep &#39;^/(usr|bin)&#39;&#xA;&#xA;/bin&#xA;/usr/bin&#xA;/usr/local/bin&#xA;/usr/local/sbin&#xA;/usr/local/sbin&#xA;/usr/local/sbin&#xA;/usr/sbin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;tweak the regex as you see fit&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Then you need to list all the commands within those directories.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following alias&amp;rsquo; give you an idea of how you might approach doing that.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;alias commands_dir=&#39;echo $PATH | tr &amp;quot;:&amp;quot; &amp;quot;\n&amp;quot; | sort | egrep &amp;quot;^/(usr|bin)&amp;quot;&#39;&#xA;alias commands=&#39;for i in $(commands_dir):; do eval &amp;quot;ls -l $i&amp;quot;; done&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Does anyone know of a better way? I&amp;rsquo;d ❤️ to hear about it&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/computers-101/</guid>
      <link>https://www.integralist.co.uk/posts/computers-101/</link>
      <pubDate>Tue, 30 Jan 2018 00:00:00 +0000</pubDate>
      <title>Computers 101: terminals, kernels and shells</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I started learning about statistics because I found myself doing a lot of operational monitoring (i.e. making systems more observable, instrumenting individual services, and monitoring that data via custom built dashboards).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although, for the most part, everything worked as expected and I generally understood the data I was seeing visualised, I wanted to be sure I wasn&amp;rsquo;t missing any important information (or worse, mis-representing the data).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This began my journey into learning about statistics (as a complete beginner). I picked up a book on the subject and started taking notes.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I highly recommend reading &lt;a href=&#34;http://shop.oreilly.com/product/9780596527587.do&#34; target=&#34;_blank&#34;&gt;Head First Statistics&lt;/a&gt; which is where the majority of this information has stemmed. There you&amp;rsquo;ll find a lot more detail and better break downs of the ideas.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This blog post is the result of what I have learnt so far, and its motivation is to explain some of the basic concepts behind utilising statistics to represent data. This post is aimed at beginners, as I myself am very much a beginner in this space.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s begin by defining what &amp;lsquo;statistics&amp;rsquo; means&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Statistics&lt;/strong&gt; is a branch of mathematics dealing with the collection, analysis, interpretation, presentation, and organization of data &amp;ndash; &lt;a href=&#34;https://en.wikipedia.org/wiki/Statistics&#34; target=&#34;_blank&#34;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;OK, that seems reasonable enough. Statistics is an &amp;lsquo;umbrella&amp;rsquo; term that encapsulates the complete pipeline of how data is acquired, analysed and visualised. So what &lt;em&gt;is&lt;/em&gt; data and what does it look like? Let&amp;rsquo;s move onto the next section where we can begin to clarify and understand it a bit more&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;information-vs-data&#34;&gt;Information vs Data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re like me, you may well have confused the words &amp;ldquo;data&amp;rdquo; and &amp;ldquo;information&amp;rdquo; as being the same thing. But there are actually important differences that should be understood:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt;: is the &lt;em&gt;raw&lt;/em&gt; facts/figures.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Information&lt;/strong&gt;: data that has extra context/meaning applied.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For example, raw data might look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[3, 5, 7]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Whereas &lt;em&gt;information&lt;/em&gt; would be the taking of that raw data and giving it extra context. So, in this example, those three data points could represent the age of three children. In a classic CSV (comma separated values) format (which is used for storing &amp;lsquo;tabular&amp;rsquo; data), it might be represented like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Age&#xA;3,&#xA;5,&#xA;7&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;data is either &amp;ldquo;numerical&amp;rdquo; (dealing with numbers), &amp;ldquo;quantitative&amp;rdquo; (describing quantities) or &amp;ldquo;categorical&amp;rdquo; (data is split into categories that describe qualities or characteristics - also referred to as &amp;ldquo;qualitative&amp;rdquo;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;frequency&#34;&gt;Frequency&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with statistical data, the first thing you typically learn about is data &amp;ldquo;frequency&amp;rdquo;. Let&amp;rsquo;s start with a definition&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In statistics the frequency (or absolute frequency) of an event is the number of times the event occurred in an experiment or study. &amp;ndash; &lt;a href=&#34;https://en.wikipedia.org/wiki/Frequency_(statistics)&#34; target=&#34;_blank&#34;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Consider the following data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;3,5,5,5,7,7,2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first number &lt;code&gt;3&lt;/code&gt; and the last number &lt;code&gt;2&lt;/code&gt; both have a frequency of one, in that they only appear once throughout the entire dataset. Whereas the number &lt;code&gt;5&lt;/code&gt; has a frequency of three and the number &lt;code&gt;7&lt;/code&gt; has a frequency of two for similar reasons (i.e. &lt;code&gt;5&lt;/code&gt; appears three times and &lt;code&gt;7&lt;/code&gt; appears twice).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another way to represent this data is by defining a separate column for the frequency (which allows you to more clearly see the unique numbers that are present in the dataset):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Age, Frequency&#xA;3,   1&#xA;5,   3&#xA;7,   2&#xA;2,   1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;strictly speaking you might want to refer to the above snippet as &lt;strong&gt;information&lt;/strong&gt; rather than &lt;strong&gt;data&lt;/strong&gt; simply because the raw data now has &amp;lsquo;context&amp;rsquo; added to it which clarifies what the numbers mean.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The data/information can be visualised in many ways depending on the graph type you wish to use. Some graphs are better suited for representing certain types of data than others.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll take a look at some different graph types to see how they work, but first let&amp;rsquo;s take a moment to consider how data can trick us&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;watch-out-for-misleading-data&#34;&gt;Watch out for misleading data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following example is very contrived and silly, but it does illustrate the point about being aware of how data can be manipulated to represent what you want it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are two &amp;lsquo;line&amp;rsquo; graphs. We&amp;rsquo;ll talk about this type of graph in more detail later, but effectively we create two axis and then plot our data onto the graph and draw a line between the dots.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now both graphs use the same datapoints, but the first graph is misleading the viewer, while the second graph is more accurate. Take a look and see why that might be?&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;misleadingProfitsLine&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;canvas id=&#34;profitsLine&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;p&gt;At a quick glance (or if you just didn&amp;rsquo;t know any better), you would see the first graph and think the company has some incredible profit growth. But the second graph doesn&amp;rsquo;t look as impressive?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because the first graph is zoomed in from the starting point &lt;code&gt;2.0&lt;/code&gt; whereas the first graph is zoomed out at the correct level so you can see the data in a more accurate and representative form.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See also my comment in the next section about &lt;a href=&#34;#5&#34;&gt;pie charts&lt;/a&gt;. You&amp;rsquo;ll notice there that the data can be mis-represented if not all the information is made available to the user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the data isn&amp;rsquo;t lying, it&amp;rsquo;s just the view the user has of the data isn&amp;rsquo;t accurately portrayed due to purposeful data ommission (this is a trick newspapers and academic papers use to represent a point of view they wish to push).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;pie-chart&#34;&gt;Pie Chart&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A graph, such as a pie chart, will split your data up into distinct &amp;lsquo;groups&amp;rsquo;. These groups are represented as relative percentages of the total group, meaning the total area adds up to 100%.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example pie graph that uses the data &lt;code&gt;[150,200,50]&lt;/code&gt;, which could represent (just for example) usage of certain programming languages within an organisation. The pie chart is generated based off the percentage representation of the underlying data.&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;simplePie&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Here is how the graph data is calculated:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Start by finding the total (i.e. sum all the data)&lt;br&gt;&#xA;Then calculate 1% of that total&lt;br&gt;&#xA;Finally, calculate each group&amp;rsquo;s individual percentage&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Total&lt;/strong&gt;: 150+200+50 = 400&lt;br&gt;&#xA;&lt;strong&gt;1 Percent&lt;/strong&gt;: &lt;sup&gt;400&lt;/sup&gt;&amp;frasl;&lt;sub&gt;100&lt;/sub&gt; = 4&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we know the total is 400 and 1% of that is 4 we can calculate each group&amp;rsquo;s individual percentage&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; group = 50%&lt;br&gt;&#xA;&lt;small&gt;i.e. &lt;code&gt;(400/100) * 50 = 200&lt;/code&gt;&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; group = 37.5%&lt;br&gt;&#xA;&lt;small&gt;i.e. &lt;code&gt;(400/100) * 37.5 = 150&lt;/code&gt;&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Bash&lt;/strong&gt; group = 12.5%&lt;br&gt;&#xA;&lt;small&gt;i.e. &lt;code&gt;(400/100) * 12.5 = 50&lt;/code&gt;&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll know if we&amp;rsquo;ve calculated things correctly, if the sum of the group percentages results in 100%&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;50%&lt;/strong&gt; + &lt;strong&gt;37.5%&lt;/strong&gt; + &lt;strong&gt;12.5%&lt;/strong&gt; = 100%&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Pie charts are useful for understanding &amp;lsquo;at a glance&amp;rsquo; the relative difference between groups of data. But they become less useful when the data is close together, as each &amp;lsquo;slice&amp;rsquo; becomes effectively the same size.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;misleading&#34;&gt;Misleading?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As mentioned in the previous section, all graphs can be presented in such a way as to mislead you and make you think that the reality is different to what it really is. Pie charts are no exception.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pie charts visually &amp;lsquo;display&amp;rsquo; their information in relative percentages, but if they don&amp;rsquo;t also show (or include somewhere near the graph) the &lt;em&gt;frequency&lt;/em&gt; for each group within the pie chart, then the graph could be misleading.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason it can be misleading is because without the frequency you can&amp;rsquo;t identify whether the data being presented is &lt;em&gt;consistent&lt;/em&gt;. This may or may not indicate whether it&amp;rsquo;s fair to compare the data in this way (as it might not be truly representative).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whether that is the case or not depends on the type of data being presented. In our case it&amp;rsquo;s not really an issue for two reasons:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We include the &lt;em&gt;frequency&lt;/em&gt; data in our pie chart.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;hover over or click on the chart to view frequency.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Our data is simple enough to not be mis-represented.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;So you have to be careful with data to make sure it&amp;rsquo;s as inclusive as possible or that you&amp;rsquo;re explicit about what you&amp;rsquo;re focusing on or how the data might be lacking.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Earlier we mentioned a problem of data groups percentages being too close together resulting in a graph that was hard to distinguish subtle differences. In those scenarios you might find a more suitable option would be the bar chart&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bar-chart&#34;&gt;Bar Chart&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you wanted to see the &amp;lsquo;programming language&amp;rsquo; data in a format that is more suitable for subtle differences, then one option would be a bar chart.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s view the dataset we have:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Language, Frequency&#xA;Go,       150&#xA;Python,   200&#xA;Bash,     50&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When dealing with a horizontal bar chart (directly below), the individual data groups (in this case: the programming languages) are placed along the y axis, while with a vertical bar chart (example below that) they&amp;rsquo;re placed along the x axis.&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;simpleBar&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;canvas id=&#34;simpleBarVert&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;p&gt;One thing to notice about a bar chart is that the &lt;em&gt;width&lt;/em&gt; of the bar is the same (doesn&amp;rsquo;t matter if it&amp;rsquo;s a horizontal or vertical variation, their widths stay consistent). It&amp;rsquo;s the &lt;em&gt;length&lt;/em&gt; of each bar that&amp;rsquo;s actually important.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because the length represents the frequency of the group&amp;rsquo;s data. This can trip people up, as they might mistake a bar chart for a &amp;lsquo;histogram&amp;rsquo;, where the width of the bar &lt;em&gt;does&lt;/em&gt; change in relation to the frequency (don&amp;rsquo;t worry, we&amp;rsquo;ll come back to histograms later).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;stacked-bars&#34;&gt;Stacked Bars&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now imagine you wanted to visualise data that represented how much people liked or disliked specific programming languages (this is different to the previous data which was the general usage of programming languages).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The dataset might look something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Language, Like, Dislike&#xA;Go,       290,  10&#xA;Python,   150,  100&#xA;Bash,     50,   250&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To represent this multifaceted data you could use a specific type of bar chart known as a &amp;lsquo;stacked&amp;rsquo; bar chart (see below). This type of graph is useful because it represents both the frequency &lt;em&gt;and&lt;/em&gt; the relative percentage of the various data types.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;stacked bar charts are also known as &amp;lsquo;segmented&amp;rsquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;canvas id=&#34;stackedBar&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s less likely for this chart to be mis-represented because the &lt;em&gt;length&lt;/em&gt; of each bar is based on the data frequency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can see for the groups &amp;ldquo;Go&amp;rdquo; and &amp;ldquo;Bash&amp;rdquo; we&amp;rsquo;ve had a consistent number of reports (300 in total), and so when the values are visualised as a percentage the length of the bars are the same.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whereas the &amp;ldquo;Python&amp;rdquo; group has less data frequency compared to the other groups (only 250 in total, where the other groups were 300), and so although it correctly represents that data as a percentage (60% were &amp;ldquo;like&amp;rdquo; vs 40% &amp;ldquo;dislike&amp;rdquo;) it&amp;rsquo;s still not as representative as a whole in comparison to the other data groups we have. Ideally each group would have consistent frequencies.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;split-bars&#34;&gt;Split Bars&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Another type of bar chart is called &amp;lsquo;split-category&amp;rsquo; and is useful for &lt;em&gt;comparing frequencies&lt;/em&gt; (unlike the stacked/segmented bar chart which compares frequency but represents them visually in percentages).&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;splitBar&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;h2 id=&#34;histograms&#34;&gt;Histograms&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve yet to find a charting library that let&amp;rsquo;s me create an actual histogram in the strict definition (most libraries seem to call standard bar charts &amp;lsquo;histograms&amp;rsquo;?), which makes it hard for me to visually demonstrate them, unless I hand draw a chart (which is what I&amp;rsquo;ve had to resort to below).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;differences&#34;&gt;Differences?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Based on what I&amp;rsquo;ve read, there are some key differences between histograms and standard bar charts. These are:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The &amp;lsquo;area&amp;rsquo; (width &lt;em&gt;and&lt;/em&gt; height) of each bar is proportional to its frequency.&lt;/li&gt;&#xA;&lt;li&gt;There should be no gaps between each bar.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The reason for histogram bar sizes being proportional (unlike a traditional bar chart †) is because histograms are usually best suited to dealing with &lt;strong&gt;&lt;em&gt;grouped numerical data&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† remember: with a traditional bar chart, each bar width is the same and only the bar &amp;lsquo;length&amp;rsquo; is relevant (as it&amp;rsquo;s determined by the frequency).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;calculating-dimensions&#34;&gt;Calculating dimensions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When constructing a histogram, you&amp;rsquo;ll place the groups on the x axis and make the width of each bar the same as the range it covers; while placing the frequencies for each group on the y axis and make the length of the bar match the frequency value for that group.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Doing this is fine, as long as the groups have a consistent range (i.e. they all have the same interval size, like: &lt;code&gt;0-5,5-10,10-15&lt;/code&gt; and whose range/interval distance are all five).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;inconsistent-ranges&#34;&gt;Inconsistent Ranges&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;But in some datasets a single group can cover a much wider range than the other groups. For example, consider a dataset for gaming hours played by a group of 17 users:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Hours, Frequency&#xA;0-1,   5&#xA;1-20,  2&#xA;20-22, 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here &amp;lsquo;hours&amp;rsquo; is the grouped numerical data. As explained above, we would put the frequency on the y axis and the grouped data along the x axis (see below for an example graph).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/disproportionate_historgram.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/disproportionate_historgram.png&#34; alt=&#34;disproportionate historgram&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we can see our first bar &amp;ldquo;0-1&amp;rdquo; spreads only one interval and &amp;ldquo;20-22&amp;rdquo; spreads only two intervals, whereas the middle bar &amp;ldquo;1-20&amp;rdquo; spreads over nineteen intervals!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The problem with the above graph is that the height of the middle bar is wrong as we&amp;rsquo;ve set it to be as high as the frequency value itself (and the third bar is incorrect too!), which normally would be fine if the interval range were the same across all groups, but in this case it isn&amp;rsquo;t the correct approach due to each group covering a different range from each other.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In using this data, the &lt;code&gt;1-20&lt;/code&gt; group&amp;rsquo;s &lt;em&gt;area&lt;/em&gt; could mistakenly look disproportionately large (the &lt;code&gt;20-22&lt;/code&gt; group also has a different range so that would be a problem as well).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to solve the problem of disproportionate sizes (when dealing with multi-range groups), we have to make sure that &lt;em&gt;both&lt;/em&gt; the width and height (or &amp;lsquo;area&amp;rsquo;) of the group is proportional.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-to-fix-the-proportions&#34;&gt;How to fix the proportions?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To fix the bar area size problem we need a different calculation for determining the &amp;lsquo;height&amp;rsquo; of each bar (also known as the frequency density):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;frequency / range = frequency density&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For example, the range for &lt;code&gt;1-20&lt;/code&gt; is 19 and its frequency is 2:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;2 / 19 = 0.10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Meaning the height of the bar (its frequency density) for &lt;code&gt;1-20&lt;/code&gt; should be set to &lt;code&gt;0.10&lt;/code&gt; and not to the frequency value itself (which was &lt;code&gt;2&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You would then apply this calculation to the height of each group/bar (see below). You&amp;rsquo;ll see we also needed to change the height of the &lt;code&gt;20-22&lt;/code&gt; group based on this new area calculation (&lt;code&gt;10 / 2 = 5&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/disproportionate_historgram_area_fixed.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/disproportionate_historgram_area_fixed.png&#34; alt=&#34;disproportionate historgram area fixed&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I appreciate the difference between the original height of 2 vs the correct height of 0.10 (for the range &lt;code&gt;1-20&lt;/code&gt;) and 10 vs 5 (for the range &lt;code&gt;20-22&lt;/code&gt;), when using this contrived example, isn&amp;rsquo;t exactly ground breakingly different; but this is just to help you understand the general idea behind calculating histogram areas for groups that have inconsistent ranges.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can now see the overall area (or shape) for each bar represents the actual frequency, and can be calculated like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;frequency = range × frequency density&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Example: the group &lt;code&gt;20-22&lt;/code&gt; had a range of 2 and a frequency density of 5.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we were to look at the graph by itself, which only shows the proportional area relative to the other groups (i.e. it only shows the frequency density and the range) we could reverse engineer/calculate the actual &lt;em&gt;frequency value&lt;/em&gt; with the abstract calculation above (&lt;code&gt;2 * 5 = 10&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;frequency-density&#34;&gt;Frequency Density?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As alluded to earlier, the height of each bar indicates the frequency density, which itself is best explained via an analogy:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a tall glass and you pour a set amount of liquid into it that fills the glass to approximately &lt;sup&gt;3&lt;/sup&gt;&amp;frasl;&lt;sub&gt;4&lt;/sub&gt;. If you now pour that liquid into a much wider glass, the liquid amount hasn&amp;rsquo;t changed but the height has changed. It&amp;rsquo;ll be at a lower level as the liquid has spread out more across the available glass space.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The frequency density is &lt;em&gt;related&lt;/em&gt; to frequency but is focused more around its &amp;lsquo;concentration&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we wanted to calculate the &lt;em&gt;total frequency&lt;/em&gt; for the entire dataset then we would use the following calculation: &lt;code&gt;group range x group frequency density&lt;/code&gt; for each group (which gives us the frequency for each group) and then we sum each of the frequencies together.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is as far as I got with histograms, as I felt I had learnt enough to be dangerous in a conversation. There may well be nuances, pros/cons and other aspects to histograms I&amp;rsquo;ve not fully understood. I&amp;rsquo;d welcome anyone who knows more to educate me on this :-)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;line-graphs&#34;&gt;Line Graphs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve already seen a couple of example line graphs at the start of this post. To create a line graph you require two axis (x and y) and the data to be mapped onto different points across these axis&amp;rsquo; which allow us to plot a line between the dots we mark.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These types of graphs are best for identifying &lt;em&gt;trends&lt;/em&gt; in your data and are most useful when applied across numerical data (such as time, which again helps with overarching trending patterns).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;compare this to bar charts, which are generally better for comparing values or categories.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;There are various types of line graphs, one is known as an &amp;ldquo;accumulative frequency graph&amp;rdquo; which we can demonstrate using the earlier grouped dataset of hours played online. If we were to take the hours data, we could graph a specific subset view of that data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, we can visualise the number of people who played for a specific number of hours. So we could say: &amp;ldquo;how many users were playing online for up to five hours?&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way we do this is by adding up all the previous groups frequencies, which determines the upper limit for each group. So for example, using our previous data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Hours, Frequency&#xA;0-1,   5&#xA;1-20,  2&#xA;20-22, 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can calculate the cumulative frequency like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0-1:   upper limit = 1  (total/cumulative frequency: 5)&#xA;1-20:  upper limit = 20 (total/cumulative frequency: 5+2=7)&#xA;20-22: upper limit = 22 (total/cumulative frequency: 5+2+10=17)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Resulting in the following cumulative frequencies:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0-1:   5&#xA;1-20:  7&#xA;20-22: 17&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can now plot these onto a line graph by placing the cumulative frequencies onto the y axis and the groups across the x axis. Then mark onto the graph the upper limits against the relevant cumulative frequency and finally join up the dots:&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;simpleLine&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In the above example graph, if we asked &amp;ldquo;how many people were playing for up to 21 hours?&amp;rdquo; the answer would be approximately 11 people.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;averages&#34;&gt;Averages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When looking at data and graphs, people are generally interested in &amp;lsquo;averages&amp;rsquo; because they help us better gauge what/where the majority is. But there are actually three different types of &amp;lsquo;average&amp;rsquo;, and each one has a different purpose:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;mean average&lt;/li&gt;&#xA;&lt;li&gt;median average&lt;/li&gt;&#xA;&lt;li&gt;mode average&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;mean&#34;&gt;Mean&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;mean&amp;rsquo; average is the average that most people think about. To calculate the mean you would sum every number in your dataset and then divide the result by the number of elements in the dataset. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dataset = [2,5,9]&#xA;sum = 16 (2 + 5 + 9)&#xA;mean = 3 (16 / 3)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the mean average can be expressed mathematically by &lt;code&gt;Σx/n&lt;/code&gt;. When broken down &lt;code&gt;Σx&lt;/code&gt; (pronounced &amp;ldquo;sigma x&amp;rdquo;) is a quick way of saying &amp;ldquo;add together the values of all the x&amp;rsquo;s&amp;rdquo; without having to say what the values are. This also can be expressed with the Greek symbol &lt;code&gt;μ&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;When dealing with datasets that have frequencies we need to ensure the frequencies are included as part of the calculation. For example, consider the following data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Age:       19, 20, 21&#xA;Frequency: 1,  3,  1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What the frequencies indicate is that 19 and 21 only appear once, whereas 20 appears three times. So when summing the values (&lt;code&gt;Σx&lt;/code&gt;) this &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; mean &lt;code&gt;19+20+21&lt;/code&gt;, instead it means &lt;code&gt;19+20+20+20+21&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similarly, when dividing by the number of items in the dataset (the &lt;code&gt;n&lt;/code&gt; in &lt;code&gt;Σx/n&lt;/code&gt;) it means dividing by 5 (&lt;code&gt;1+3+1&lt;/code&gt;) and not taking the number of frequencies literally, so &lt;em&gt;not&lt;/em&gt; dividing by 3 (&lt;code&gt;1,3,1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Resulting in a calculation that gives us the mean average as &lt;code&gt;20&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(19+20+20+20+21) / (1+3+1) = 20&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;or&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;100 / 5 = 20&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this type of mean average (i.e. one applied to data that has frequencies associated with it) can be expressed mathematically with &lt;code&gt;Σfx/Σf&lt;/code&gt; and equates to &amp;ldquo;multiply each number by its frequency, then add the results together&amp;rdquo; (&lt;code&gt;Σfx&lt;/code&gt;), then &amp;ldquo;divide the result by the sum of frequencies&amp;rdquo; (&lt;code&gt;Σf&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s an issue with using the mean average, and that&amp;rsquo;s &lt;strong&gt;outliers&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following dataset:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Age:       19, 20, 21, 145, 147&#xA;Frequency: 3,  6,  3,  1,   1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we wanted to calculate the average age (using &lt;code&gt;Σfx/Σf&lt;/code&gt;), that would look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;((3×19) + (6×20) + (3×21) + 145 + 147) / (3+6+3+1+1) = 38&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is telling us the average age is 38. That number doesn&amp;rsquo;t actually &lt;em&gt;exist&lt;/em&gt; in the dataset!?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What has happened is that the outliers (the large numbers at the end of the dataset: &lt;code&gt;145, 147&lt;/code&gt;) have &lt;em&gt;pulled&lt;/em&gt; the mean higher, meaning the data is &amp;ldquo;skewed&amp;rdquo;. Data can be skewed to the left (the mean is pulled lower) or it can be skewed to the right (the mean is pulled higher - as in the case of our example above).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we say skewed &amp;ldquo;left&amp;rdquo; or &amp;ldquo;right&amp;rdquo; because when sorting the data in ascending order you would see the outliers are either mainly to the left or the right (depending on the data).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If we were to look at this on a line histogram graph we would notice this &amp;lsquo;pulling&amp;rsquo; of the mean:&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;meanOutliers&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the above graph you can see the longer &amp;lsquo;tail&amp;rsquo; that indicates the outliers.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;How can we deal with outliers? Well, this is where the median can help&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;median&#34;&gt;Median&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The median gives us the &lt;em&gt;exact middle&lt;/em&gt; of our data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To calculate this you would take all the numbers (inc. their frequencies) sort them, and then select whatever is the middle number. Let&amp;rsquo;s see this using the following dataset:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Age:       19, 20, 21, 145&#xA;Frequency: 3,  6,  3,  1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s include the frequencies and sort the numbers in ascending order:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 145&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s 13 numbers in total (i.e. sum the frequencies &lt;code&gt;Σf&lt;/code&gt; like so: &lt;code&gt;3+6+3+1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to find the exact middle we just divide the number by 2 (which gives us 6.5) and then round it (so it becomes 7). Meaning the seventh number in the dataset is the exact middle: &lt;code&gt;20&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;alternatively it can be abstracted to &lt;code&gt;(n+1)/2&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But what happens with a dataset with an &lt;em&gt;even&lt;/em&gt; set of numbers? Well, in that case you need to take the mean of the two middle numbers (i.e. sum them and divide the result by 2). Consider the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;19, 19, 20, 20, 20, 21, 22, 23, 145, 147&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are 10 numbers so if we divide by 2 we&amp;rsquo;ll get 5. If you count five items inwards from either the start or the end of the dataset, you&amp;rsquo;ll find you land on two different numbers (in this case 20 and 21).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in this scenario you sum 20 and 21 (&lt;code&gt;20+21 = 41&lt;/code&gt;) and divide the result by two (&lt;code&gt;41/2 = 20.5&lt;/code&gt;). Meaning the median of the above dataset is &lt;code&gt;20.5&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;what you&amp;rsquo;ll typically find is that if the data is &lt;em&gt;symmetrical&lt;/em&gt; then the mean and the median will result in the same value.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But what happens if a dataset has multiple clusters of values, so for example the dataset includes values that are at both low and high ends?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider a baby swimming group; this would include very young ages (i.e. the babies) and older ages (i.e. the parents) and so you might find the mean and median both result in an average age for that dataset as being mid-teens (which &lt;em&gt;traditionally&lt;/em&gt; wouldn&amp;rsquo;t necessarily be correct - depending on the social/cultural environment). Also the results can vary significantly if there are more babies or parents joining the class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution to this problem is to return the most popular value (the one with the highest frequency). This is where the &amp;ldquo;mode&amp;rdquo; average can help&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;mode&#34;&gt;Mode&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The mode is the third and final type of average, and it aims to return the value with the highest frequency. Which means the value that it gives as the result &lt;strong&gt;MUST&lt;/strong&gt; exist within the dataset (unlike the mean which could result in a value that &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; exist).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if there are multiple frequencies with the same value, then the dataset is considered &amp;ldquo;bimodal&amp;rdquo;. Meaning there are multiple modes for the dataset.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The mode average is the only average that works not just on numerical data but categorical data. When you’re dealing with categorical data, the mode is the most frequently occurring category.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are the steps for calculating the mode:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Identify all the distinct categories (or values) in your dataset.&lt;/li&gt;&#xA;&lt;li&gt;Document the frequency for each categoy (or value).&lt;/li&gt;&#xA;&lt;li&gt;Select the values with the highest frequency to find the mode.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The mode is considered most useful when dealing with data that has a small number of modes, or when the data is categorical instead of numerical (remember: neither the mean nor the median can be used with categorical data). But if there are lots of modes identified, then the mode average can end up being &lt;em&gt;less&lt;/em&gt; useful over other averages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see some example data and identify the mode average in each:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Values:    1, 2, 3&#xA;Frequency: 3, 7, 4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The mode for the above dataset is &lt;code&gt;2&lt;/code&gt; (as it is the value that has the highest frequency).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Categories: Red, Yellow, Green&#xA;Frequency:  20,   7,      4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The mode for the above dataset is the &amp;ldquo;Red&amp;rdquo; category (as it is the category has the highest frequency).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Values:    1, 2, 3&#xA;Frequency: 3, 7, 7&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above dataset actually contains multiple modes (i.e. multiple modes with the same frequency which happens to be the highest in the set). The modes being &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt; (whose frequency is &lt;code&gt;7&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;which-average-to-use&#34;&gt;Which average to use?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine we have staff, managers and a CEO and they&amp;rsquo;re all determining how pay rises should be calculated when based on the average salary. Below is a suggestion as to which average each one of them might suggest using and why:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Staff&lt;/strong&gt;: median&lt;br&gt;&#xA;staff prefer the median average as it helps reduce the effect of the CEO&amp;rsquo;s salary as an outlier.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managers&lt;/strong&gt;: mean&lt;br&gt;&#xA;the large CEO salary is an outlier, thus resulting in the mean being skewed to the right - so this is the preferred average of the managers as it brings a much larger pay rise!&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;CEO&lt;/strong&gt;: mode&lt;br&gt;&#xA;considering there are many more staff than managers (or CEOs), the CEO prefers the mode because it results in the staff salary being the basis of a pay rise - resulting in paying out a lot less than is fair.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the median is the most &amp;lsquo;fair&amp;rsquo; when calculating a pay rise in this example scenario.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;ranges&#34;&gt;Ranges&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Averages help identify the center of our data (and via various perspectives as we&amp;rsquo;ve already seen: mean, median and mode). But this isn&amp;rsquo;t useful when it comes to understanding how the data itself varies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ranges help explain how data is &lt;em&gt;distributed&lt;/em&gt; and informs you of how far apart your highest and lowest values are. In other words, the range is a way of measuring how &lt;em&gt;spread&lt;/em&gt; out a set of values are (almost like we&amp;rsquo;re measuring the width of the dataset).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To calculate the range of a dataset you require the &amp;ldquo;upper bound&amp;rdquo; and the &amp;ldquo;lower bound&amp;rdquo;. The upper bound is the highest value and similarly the lower bound is the lowest value. The range calculation is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;upper bound - lower bound = range&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But you can be in a situation where two separate datasets have different distribution of data and yet they have the same &amp;lsquo;range&amp;rsquo; value. This is because the range only indicates the &lt;em&gt;width&lt;/em&gt; of the data and not how it&amp;rsquo;s dispersed inbetween the higher/lower bounds.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the range value is very sensitive to outliers and so it can be misleading if used to identify data distribution.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Consider this example dataset:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;On a bar chart this data could be mapped like so (where the frequencies are set on the y axis and the numerical values are set on the x axis):&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;range&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;p&gt;The range for the above data would be 4 (&lt;code&gt;5 - 1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now append an outlier value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;canvas id=&#34;rangeOutlier&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;p&gt;The range for the above data would now become 9 (&lt;code&gt;10 - 1&lt;/code&gt;) even though there are no new values inbetween. The outlier has distorted the range.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;quartiles&#34;&gt;Quartiles&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to avoid outliers we should focus on the central tendency of the data. In order to do that we need to split our data into quarters. The first and last quarters (which typically contain outliers) can subsequently be discarded, allowing us to focus on the central quarters.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Given the earlier data (which included an outlier on the far right):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would be split into quarters like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[1, 1, 1, 2, 2,]&#xA;[2, 2, 3, 3, 3,]&#xA;[3, 3, 4, 4, 4,]&#xA;[4, 5, 5, 5, 10]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The location within the data where splits have been inserted are known as &amp;ldquo;quartiles&amp;rdquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[...] quartile [...] quartile [...] quartile [...]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The lowest quartile is called the &amp;ldquo;lower quartile&amp;rdquo; or Q1, while the highest quartile is called the &amp;ldquo;upper quartile&amp;rdquo; or Q3. The middle quartile is called the &amp;ldquo;median&amp;rdquo; or Q2 (effectively splitting the data in half).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are those splits but using the relevant names applied (Q1, Q2 and Q3):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[...] Q1 [...] Q2 [...] Q3 [...]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The range of the values in the two median quarters (inbetween Q1-Q3) are referred to as the &amp;ldquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Interquartile_range&#34; target=&#34;_blank&#34;&gt;interquartile range&lt;/a&gt;&amp;rdquo;, and provides a way to measure how values are dispersed while being less sensitive to the outliers that would have been found in the lower/upper quartiles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a (very) rough outline of where the quartiles would be found using our example dataset (each quartile is highlighted in blue). We can see that the interquartile range (the section inside of the outer blue lines) chops off the outlier that is pulling (skewing) the data to the right:&lt;/p&gt;&#xA;&#xA;&lt;canvas id=&#34;quartile&#34;&gt;&lt;/canvas&gt;&#xA;&#xA;&lt;h3 id=&#34;locating-the-lower-higher-quartiles&#34;&gt;Locating the lower/higher quartiles&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Consider the following sorted data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;4, 7, 1, 0, 3, 8, 9, 2, 5, 10, 6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there are 11 values in the above data&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The calculation for finding the lower quartile is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;N / 4 = round(result)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So this would be &lt;code&gt;11 / 4&lt;/code&gt;, which gives us the result of &lt;code&gt;2.75&lt;/code&gt; that we then round up to &lt;code&gt;3&lt;/code&gt;. Meaning the lower quartile is the third value in the dataset, so that would be the value &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The calculation for finding the higher quartile is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;lower quartile x (N / 4) = round(result)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So this would be &lt;code&gt;3 x 2.75&lt;/code&gt;, which gives us the result of &lt;code&gt;8.25&lt;/code&gt; that we then round up to &lt;code&gt;9&lt;/code&gt;. Meaning the higher quartile is the ninth value in the dataset, so that would be the value &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning the interquartile range can be found in-between the lower/upper quartile positions, thus giving us the central 50% of the data to focus on.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;percentiles&#34;&gt;Percentiles&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with quartiles (see above), you&amp;rsquo;re splitting your data into quarters. When dealing with percentiles, you&amp;rsquo;re splitting your data into percentages. Each percentage is a percentile. For example, the 20th percentile is the value that is found 20% into your data.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;quartiles are a type of percentile. For example, the lower quartile is the 25th percentile. Whereas the upper quarter is the 75th percentile. The median (or Q2) is the 50th percentile.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Percentiles are generally used as a means for identifing values for a specific percentage of your users. For example, if your dataset reported performance numbers, then you could look at the value at the 95th percentile of the data and say &amp;ldquo;95% of our users are seeing this measure of performance&amp;rdquo;. Which is more relevant than looking at the average (i.e. mean/median/mode) of that performance data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another typical example given for understanding the purpose of percentiles is to imagine you scored 50 in a test, and the value in the test results dataset at the 90th percentile was 50, then this would mean you had scored the same as (or beat the score of) 90% of your class who took the test.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;calculating-percentiles&#34;&gt;Calculating Percentiles&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to calculate percentiles of a dataset you first need to sort the data in ascending order. Once this is done you need to identify &lt;code&gt;N&lt;/code&gt; which is the number of values you have in your dataset. From there you can do the following calculation (where &lt;code&gt;K&lt;/code&gt; is the percentile you want the value for):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;K x (N / 100)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If the result is not an integer, then round it up and that will give you the position of your percentile. Otherwise if it &lt;em&gt;is&lt;/em&gt; an integer, then the value can be found in-between the integer position and the next position along so take the average of the two numbers at those positions to find the percentile value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if you have 125 numbers in a dataset and you wished to see the 10th percentile for those values, then the calculation would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10 x (125 / 100) = round_up(12.5) -&amp;gt; 13&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So the 10th percentile would be the value at position 13 in your dataset.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;variance&#34;&gt;Variance&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Measuring the &amp;lsquo;spread&amp;rsquo; of data isn&amp;rsquo;t always as useful as being able to measure the consistency of that spread, in that if our data represented player scores in a game, then we might want to identify how consistent (or reliable) a player was. Did they perform better and more reliably than another player?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way to measure this is by looking at the mean and then looking at the distance of other values from the mean. This will give us the &amp;ldquo;variation&amp;rdquo; we&amp;rsquo;re looking for. The closer values are to the mean, the more consistent they are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So going back to the idea of a dataset that reports game player performance. Imagine we have two players (A and B). Both have a mean value that is the same, but player A has a closer spread of values than player B. This means player A is more consistent with their scoring.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The approach for measuring the spread of data that we will look at is called the &amp;ldquo;variance&amp;rdquo; and it specifically measures, not from the &amp;lsquo;mean&amp;rsquo;, but the &amp;lsquo;mean squared&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for deciding to measure the spread of values from the &amp;lsquo;mean squared&amp;rsquo; is because maths (read &lt;a href=&#34;http://shop.oreilly.com/product/9780596527587.do&#34; target=&#34;_blank&#34;&gt;Head First Statistics&lt;/a&gt; for the gory details). To be a little more specific, it&amp;rsquo;s because if we don&amp;rsquo;t calculate things from the mean squared it can result in an incorrect value such as zero.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The variance calculation is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Σ(μ-x)²/n&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That might look a little hairy, but most of these symbols we&amp;rsquo;ve already seen.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;μ&lt;/code&gt;: this is the dataset mean (which was shorthand for &lt;code&gt;Σx/n&lt;/code&gt;).&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Σ&lt;/code&gt; represents the sum of a dataset&amp;rsquo;s values.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;x&lt;/code&gt; is the value for a particular dataset item.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;n&lt;/code&gt; is the number of items in the dataset.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Σx&lt;/code&gt; thus means: sum all values in the dataset.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Σx/n&lt;/code&gt; thus means: divide the total sum of numbers in the dataset by the number of items in the dataset.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Σ(μ-x)²&lt;/code&gt; thus means: we square the result of &lt;code&gt;μ-x&lt;/code&gt; and sum &lt;code&gt;Σ&lt;/code&gt; all the resulting values.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For example, imagine we have the following data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1, 2, 9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The mean average for this data is &lt;code&gt;4&lt;/code&gt;. The distance between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt; (e.g. &lt;code&gt;4&lt;/code&gt; is three numbers away from &lt;code&gt;1&lt;/code&gt;: so count from &lt;code&gt;1&lt;/code&gt; three numbers away and you&amp;rsquo;ll reach &lt;code&gt;4&lt;/code&gt; like so, &lt;code&gt;2, 3, 4&lt;/code&gt;). The distance between &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt; is &lt;code&gt;2&lt;/code&gt;, and the distance between &lt;code&gt;9&lt;/code&gt; and &lt;code&gt;4&lt;/code&gt; is &lt;code&gt;-5&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hence the resulting distances we get from the mean are: &lt;code&gt;3, 2, -5&lt;/code&gt;. There&amp;rsquo;s more to do, but first let&amp;rsquo;s clarify the negative/postive aspect of these numbers (i.e. if you&amp;rsquo;re confused about why the distance between &lt;code&gt;9&lt;/code&gt; and the mean is &lt;code&gt;-5&lt;/code&gt; and not &lt;code&gt;5&lt;/code&gt;, then read on)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You need to realise when measuring the distance to the mean that you&amp;rsquo;re actually counting either negative or positive in direction (this becomes clearer where you look at numbers visually):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1, 2, 3, [4], 5, 6, 7, 8, 9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve put a square bracket around the number &lt;code&gt;4&lt;/code&gt; to indicate that it&amp;rsquo;s the mean average.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If we look at the number &lt;code&gt;1&lt;/code&gt; and count the distance to &lt;code&gt;4&lt;/code&gt;, we&amp;rsquo;re effectively counting &lt;em&gt;forward&lt;/em&gt; (i.e. positive) towards &lt;code&gt;4&lt;/code&gt; (similarly with the number &lt;code&gt;2&lt;/code&gt;). But with &lt;code&gt;9&lt;/code&gt; we have to count &lt;em&gt;backwards&lt;/em&gt; (i.e. negative) towards &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example: counting &lt;code&gt;8,7,6,5,4&lt;/code&gt; shows that &lt;code&gt;9&lt;/code&gt; is five numbers away from &lt;code&gt;4&lt;/code&gt;. But as we&amp;rsquo;re treating this as a negative distance, the value is &lt;code&gt;-5&lt;/code&gt;. Whereas when calculating the distance from either &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt; to the mean, the mean (&lt;code&gt;4&lt;/code&gt;) is ahead of it and so you count positive not negative.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK so we now have the distances &lt;code&gt;3, 2, -5&lt;/code&gt;, from here we need to square these numbers and then add them up (we have to square the numbers otherwise the sum result would be zero).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, we divide by &lt;code&gt;N&lt;/code&gt; (the number of items in the dataset).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This ultimately gives us the &amp;ldquo;variance&amp;rdquo; of &lt;code&gt;12.67&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;here&amp;rsquo;s a shorter calculation for the variance &lt;code&gt;Σx²/n - μ²&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason the variance is useful is because it has provided the measure of distance from the mean based on every value in the dataset. The downside to this approach is that you&amp;rsquo;ve calculated the variance from the mean &lt;em&gt;squared&lt;/em&gt; of the dataset and not just the mean.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to have a more relative variance number (i.e. our variance result is based on the mean squared, but in practice we&amp;rsquo;ll be dealing mainly with a normal mean value, and not a &lt;em&gt;squared&lt;/em&gt; mean value) we&amp;rsquo;ll want to use something called &amp;ldquo;standard deviation&amp;rdquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;standard-deviation&#34;&gt;Standard Deviation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;All standard deviation means is: take the variance result and find the square root.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we calculate the standard deviation of the variance value &lt;code&gt;12.67&lt;/code&gt; we&amp;rsquo;ll find the result is &lt;code&gt;3.56&lt;/code&gt; and so that value is the &lt;em&gt;actual&lt;/em&gt; distance most values are away from the mean.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You would then compare this standard devication to a standard deviation of another player&amp;rsquo;s results to see which player ultimately performed better overall (i.e. if the standard deviation for player A was smaller than player B, then player A is a more consistent player).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;standard deviation has its own Greek symbol &lt;code&gt;σ&lt;/code&gt; (referred to as the lowercase Sigma). Remember to calculate &lt;code&gt;σ&lt;/code&gt; you start by calculating the variance, and then take the square root.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Some other real-world examples would be a company that manufactures machine parts. For them, they want the standard deviation for their data to be small so they can be sure all the parts they build are the same size. Whereas if you were inspecting wages across a large organisation you would likely find that the standard deviation naturally becomes quite large.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Standard deviation is also measured in the same units as your data. So if your dataset values are, for example, centimeters and the standard deviation is &lt;code&gt;1&lt;/code&gt;, this means that the values are typically 1 centimeter away from the mean.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So there we have it, a run through of some statistic basics. We&amp;rsquo;ve covered a few different graph types (pie, bar, histograms, line) and explained what averages are and how they&amp;rsquo;re calculated in different scenarios. We&amp;rsquo;ve also looked at how data is distributed and how you might measure that to identify whether some results are more consistent than others.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Statistics is such a large topic area, and as far as I can tell, this is really only scratching the surface. To be honest I&amp;rsquo;m not sure how much further I myself will go with my learning. I feel I now have enough understanding to help me get by in my work and know enough to be dangerous in conversation. Otherwise if there&amp;rsquo;s anything I discover is missing in future, I&amp;rsquo;ll be sure to return and update this post accordingly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thanks for reading. Hopefully there was something useful in here for you.&lt;/p&gt;&#xA;&#xA;&lt;script src=&#34;../../assets/js/Chart.bundle.min.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;p&gt;&lt;script&gt;&#xA;var chartColors = {&#xA;&#x9;red: &amp;lsquo;rgb(255, 99, 132)&amp;rsquo;,&#xA;&#x9;orange: &amp;lsquo;rgb(255, 159, 64)&amp;rsquo;,&#xA;&#x9;yellow: &amp;lsquo;rgb(255, 205, 86)&amp;rsquo;,&#xA;&#x9;green: &amp;lsquo;rgb(75, 192, 192)&amp;rsquo;,&#xA;&#x9;blue: &amp;lsquo;rgb(54, 162, 235)&amp;rsquo;,&#xA;&#x9;purple: &amp;lsquo;rgb(153, 102, 255)&amp;rsquo;,&#xA;&#x9;grey: &amp;lsquo;rgb(201, 203, 207)&amp;rsquo;&#xA;};&lt;/p&gt;&#xA;&#xA;&lt;p&gt;function alpharize(rgb) {&#xA;  // Usage: alpharize(chartColors.red)&#xA;  var result = /((\d{2,3}), (\d{2,3}), (\d{2,3})/i.exec(rgb);&#xA;  var colors = {}&#xA;  if (result) {&#xA;    colors[&amp;lsquo;r&amp;rsquo;] = parseInt(result[1], 16);&#xA;    colors[&amp;lsquo;g&amp;rsquo;] = parseInt(result[2], 16);&#xA;    colors[&amp;lsquo;b&amp;rsquo;] = parseInt(result[3], 16);&#xA;    return &amp;lsquo;rgba(&amp;rsquo; + colors[&amp;lsquo;r&amp;rsquo;] + &amp;lsquo;, &amp;rsquo; + colors[&amp;lsquo;g&amp;rsquo;] + &amp;lsquo;, &amp;rsquo; + colors[&amp;lsquo;b&amp;rsquo;] + &amp;lsquo;, 0.5)&amp;rsquo;;&#xA;  };&lt;/p&gt;&#xA;&#xA;&lt;p&gt;return &amp;lsquo;rgba(201, 203, 207, 0.5)&amp;rsquo;; // grey&#xA;}&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxLine = document.getElementById(&amp;ldquo;misleadingProfitsLine&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myLineChart = new Chart(ctxLine, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;line&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;    &amp;ldquo;labels&amp;rdquo;:[&amp;ldquo;January&amp;rdquo;,&amp;ldquo;February&amp;rdquo;,&amp;ldquo;March&amp;rdquo;,&amp;ldquo;April&amp;rdquo;,&amp;ldquo;May&amp;rdquo;,&amp;ldquo;June&amp;rdquo;],&#xA;    &amp;ldquo;datasets&amp;rdquo;:[{&#xA;        &amp;ldquo;label&amp;rdquo;:&amp;ldquo;Misleading Company Profits&amp;rdquo;,&#xA;        &amp;ldquo;data&amp;rdquo;:[2,2.1,2.2,2.1,2.3,2.4],&#xA;        &amp;ldquo;fill&amp;rdquo;:false,&#xA;        &amp;ldquo;borderColor&amp;rdquo;: chartColors.red,&#xA;        &amp;ldquo;lineTension&amp;rdquo;:0.1&#xA;    }]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{responsive: true}&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxLine = document.getElementById(&amp;ldquo;profitsLine&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myLineChart = new Chart(ctxLine, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;line&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;    &amp;ldquo;labels&amp;rdquo;:[&amp;ldquo;January&amp;rdquo;,&amp;ldquo;February&amp;rdquo;,&amp;ldquo;March&amp;rdquo;,&amp;ldquo;April&amp;rdquo;,&amp;ldquo;May&amp;rdquo;,&amp;ldquo;June&amp;rdquo;],&#xA;    &amp;ldquo;datasets&amp;rdquo;:[{&#xA;        &amp;ldquo;label&amp;rdquo;:&amp;ldquo;Accurate Company Profits&amp;rdquo;,&#xA;        &amp;ldquo;data&amp;rdquo;:[2,2.1,2.2,2.1,2.3,2.4],&#xA;        &amp;ldquo;fill&amp;rdquo;:false,&#xA;        &amp;ldquo;borderColor&amp;rdquo;: chartColors.blue,&#xA;    }, {label: &amp;ldquo;&amp;rdquo;,data: [0]}]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{responsive: true}&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxLine = document.getElementById(&amp;ldquo;simplePie&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myLineChart = new Chart(ctxLine, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;pie&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;    &amp;ldquo;labels&amp;rdquo;:[&amp;ldquo;Go&amp;rdquo;, &amp;ldquo;Python&amp;rdquo;, &amp;ldquo;Bash&amp;rdquo;],&#xA;    &amp;ldquo;datasets&amp;rdquo;:[{&#xA;        &amp;ldquo;label&amp;rdquo;:&amp;ldquo;Workload by Programming Language&amp;rdquo;,&#xA;        &amp;ldquo;data&amp;rdquo;:[150,200,50],&#xA;        &amp;ldquo;backgroundColor&amp;rdquo;: [chartColors.red, chartColors.yellow, chartColors.green],&#xA;    }]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{responsive: true}&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;simpleBar&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;horizontalBar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [&amp;ldquo;Go&amp;rdquo;, &amp;ldquo;Python&amp;rdquo;, &amp;ldquo;Bash&amp;rdquo;],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Programming Languages&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [150,200,50]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true,&#xA;      title: {&#xA;          display: true,&#xA;          text: &amp;ldquo;&amp;rdquo;&#xA;      }&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;simpleBarVert&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;bar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [&amp;ldquo;Go&amp;rdquo;, &amp;ldquo;Python&amp;rdquo;, &amp;ldquo;Bash&amp;rdquo;],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Programming Languages&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [150,200,50]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true,&#xA;      title: {&#xA;          display: true,&#xA;          text: &amp;ldquo;&amp;rdquo;&#xA;      }&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;stackedBar&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;horizontalBar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [&amp;ldquo;Go&amp;rdquo;, &amp;ldquo;Python&amp;rdquo;, &amp;ldquo;Bash&amp;rdquo;],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Like&amp;rdquo;,&#xA;            backgroundColor: chartColors.green,&#xA;            borderColor: chartColors.green,&#xA;            borderWidth: 1,&#xA;            data: [290,150,50]&#xA;        },{&#xA;            label: &amp;ldquo;Dislike&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [10,100,250]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true,&#xA;      title: {&#xA;          display: true,&#xA;          text: &amp;ldquo;&amp;rdquo;&#xA;      },&#xA;      scales: {&#xA;        xAxes: [{&#xA;            stacked: true&#xA;        }],&#xA;        yAxes: [{&#xA;            stacked: true&#xA;        }]&#xA;      }&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;splitBar&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;bar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [&amp;ldquo;Go&amp;rdquo;, &amp;ldquo;Python&amp;rdquo;, &amp;ldquo;Bash&amp;rdquo;],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Like&amp;rdquo;,&#xA;            stack: &amp;ldquo;Stack 1&amp;rdquo;,&#xA;            backgroundColor: chartColors.green,&#xA;            borderColor: chartColors.green,&#xA;            borderWidth: 1,&#xA;            data: [290,150,50]&#xA;        },{&#xA;            label: &amp;ldquo;Dislike&amp;rdquo;,&#xA;            stack: &amp;ldquo;Stack 2&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [10,100,250]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true,&#xA;      title: {&#xA;          display: true,&#xA;          text: &amp;ldquo;&amp;rdquo;&#xA;      }&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxLine = document.getElementById(&amp;ldquo;simpleLine&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myLineChart = new Chart(ctxLine, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;line&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;  &amp;ldquo;labels&amp;rdquo;:[&amp;ldquo;0&amp;rdquo;, &amp;ldquo;1&amp;rdquo;, &amp;ldquo;2&amp;rdquo;, &amp;ldquo;3&amp;rdquo;, &amp;ldquo;4&amp;rdquo;, &amp;ldquo;5&amp;rdquo;, &amp;ldquo;6&amp;rdquo;, &amp;ldquo;7&amp;rdquo;, &amp;ldquo;8&amp;rdquo;, &amp;ldquo;9&amp;rdquo;, &amp;ldquo;10&amp;rdquo;,&#xA;            &amp;ldquo;11&amp;rdquo;, &amp;ldquo;12&amp;rdquo;, &amp;ldquo;13&amp;rdquo;, &amp;ldquo;14&amp;rdquo;, &amp;ldquo;15&amp;rdquo;, &amp;ldquo;16&amp;rdquo;, &amp;ldquo;17&amp;rdquo;, &amp;ldquo;18&amp;rdquo;, &amp;ldquo;19&amp;rdquo;, &amp;ldquo;20&amp;rdquo;,&#xA;            &amp;ldquo;21&amp;rdquo;, &amp;ldquo;22&amp;rdquo;],&#xA;    &amp;ldquo;datasets&amp;rdquo;:[{&#xA;        &amp;ldquo;label&amp;rdquo;:&amp;ldquo;Cumulative Frequencies of Hours Played&amp;rdquo;,&#xA;        &amp;ldquo;data&amp;rdquo;:[null,5,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,7,null,17],&#xA;        &amp;ldquo;fill&amp;rdquo;:false,&#xA;        &amp;ldquo;borderColor&amp;rdquo;: chartColors.red,&#xA;        &amp;ldquo;lineTension&amp;rdquo;:0.1&#xA;    }]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{&#xA;    spanGaps: true,&#xA;    responsive: true,&#xA;    scales: {&#xA;      xAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Hours&amp;rdquo;&#xA;        }&#xA;      }],&#xA;      yAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Cumulative Frequencies&amp;rdquo;&#xA;        }&#xA;      }]&#xA;    }&#xA;  }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxLine = document.getElementById(&amp;ldquo;meanOutliers&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myLineChart = new Chart(ctxLine, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;line&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;  &amp;ldquo;labels&amp;rdquo;:[19, 20, 21, 145, 147],&#xA;    &amp;ldquo;datasets&amp;rdquo;:[{&#xA;        &amp;ldquo;label&amp;rdquo;:&amp;ldquo;Ages for a group of people&amp;rdquo;,&#xA;        &amp;ldquo;data&amp;rdquo;:[3, 6, 3, 1, 1],&#xA;        &amp;ldquo;fill&amp;rdquo;:false,&#xA;        &amp;ldquo;borderColor&amp;rdquo;: chartColors.red,&#xA;        &amp;ldquo;lineTension&amp;rdquo;:0.1&#xA;    }]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{&#xA;    responsive: true,&#xA;    scales: {&#xA;      xAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Ages&amp;rdquo;&#xA;        }&#xA;      }],&#xA;      yAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Frequencies&amp;rdquo;&#xA;        }&#xA;      }]&#xA;    }&#xA;  }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;range&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;bar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [0, 1, 2, 3, 4, 5, 6],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Example of a symmetrical/balanced range&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [0, 3, 4, 5, 4, 3, 0]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxBar = document.getElementById(&amp;ldquo;rangeOutlier&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myBarChart = new Chart(ctxBar, {&#xA;    type: &amp;ldquo;bar&amp;rdquo;,&#xA;    data: {&#xA;        labels: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],&#xA;        datasets: [{&#xA;            label: &amp;ldquo;Example of an unbalanced range&amp;rdquo;,&#xA;            backgroundColor: chartColors.red,&#xA;            borderColor: chartColors.red,&#xA;            borderWidth: 1,&#xA;            data: [0, 3, 4, 5, 4, 3, 0, 0, 0, 0, 1]&#xA;        }]&#xA;    },&#xA;    options: {&#xA;      elements: {&#xA;          rectangle: {&#xA;              borderWidth: 2,&#xA;          }&#xA;      },&#xA;      responsive: true&#xA;    }&#xA;});&lt;/p&gt;&#xA;&#xA;&lt;p&gt;var ctxQuartile = document.getElementById(&amp;ldquo;quartile&amp;rdquo;).getContext(&amp;ldquo;2d&amp;rdquo;);&#xA;var myQuartileChart = new Chart(ctxQuartile, {&#xA;  &amp;ldquo;type&amp;rdquo;:&amp;ldquo;line&amp;rdquo;,&#xA;  &amp;ldquo;data&amp;rdquo;:{&#xA;    labels:[1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11],&#xA;    datasets:[{&#xA;        // y axis data - the frequencies&#xA;        label: &amp;ldquo;Example of distribution with quartile markers&amp;rdquo;,&#xA;        data:[3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 0, 0, 0, 0, 1],&#xA;        fill:false,&#xA;        borderColor: chartColors.red,&#xA;        lineTension:0.1&#xA;    },{&#xA;      label: &amp;ldquo;&amp;rdquo;,&#xA;      data:[6] // added for some breathing space&#xA;    }]&#xA;  },&#xA;  &amp;ldquo;options&amp;rdquo;:{&#xA;    responsive: true,&#xA;    scales: {&#xA;      xAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Data Values&amp;rdquo;&#xA;        },&#xA;        gridLines: {&#xA;          color: [null, null, null, null, null, &amp;ldquo;blue&amp;rdquo;, null, null, null, null, &amp;ldquo;blue&amp;rdquo;, null, null, null, null, &amp;ldquo;blue&amp;rdquo;],&#xA;          lineWidth: 5,&#xA;          borderDash: [1]&#xA;        }&#xA;      }],&#xA;      yAxes: [{&#xA;        scaleLabel: {&#xA;          display: true,&#xA;          labelString: &amp;ldquo;Frequencies&amp;rdquo;&#xA;        }&#xA;      }]&#xA;    }&#xA;  }&#xA;});&#xA;&lt;/script&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/statistics-basics/</guid>
      <link>https://www.integralist.co.uk/posts/statistics-basics/</link>
      <pubDate>Tue, 19 Dec 2017 00:00:00 +0000</pubDate>
      <title>Statistics and Graphs: The Basics</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post should serve as a guide for best practices when dealing with services that consume messages from queues and process those messages (we refer to them as QRs or &amp;lsquo;Queue Readers&amp;rsquo;). The best practices detailed below are from the perspective of both general programming idioms as well as useful performance patterns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also are focusing primarily on QRs that use the &lt;a href=&#34;http://nsq.io/&#34; target=&#34;_blank&#34;&gt;NSQ data pipeline&lt;/a&gt; and specifically for services written in Python (although I imagine most of the items discussed could translate well enough to your queue mechanism of choice).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As with all &amp;lsquo;best practice&amp;rsquo; guidelines, they are just that &amp;hellip;&lt;em&gt;guidelines&lt;/em&gt;. Not everything listed here will be applicable for your needs. So remember to start by verifying your own application&amp;rsquo;s requirements and specific use cases.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;ephemeral-channels&#34;&gt;Ephemeral Channels?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine your server instance needs to be restarted, or its &lt;a href=&#34;http://nsq.io/components/nsqd.html&#34; target=&#34;_blank&#34;&gt;nsqd daemon&lt;/a&gt; (which receives, queues, and delivers messages to clients) is unexpectedly terminated, or maybe the nsqd exceeds the allocated &lt;code&gt;mem-queue-size&lt;/code&gt; (which determines the number of messages that should be kept in memory).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Normally this would mean messages in the queue would be lost. If you’re OK with that scenario and its outcome, then you should append &lt;code&gt;#ephemeral&lt;/code&gt; to your channels&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;nsq_channel: &#39;qr_name_goes_here#ephemeral&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Otherwise, the &lt;a href=&#34;http://nsq.io/overview/design.html&#34; target=&#34;_blank&#34;&gt;default behaviour for NSQ queues&lt;/a&gt; is to persist messages on disk. Which you choose will depend on your application and how critical you feel the messages are.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;fail-quickly&#34;&gt;Fail quickly&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When processing a high throughput of messages it&amp;rsquo;s beneficial to identify &lt;em&gt;invalid&lt;/em&gt; messages quickly, then mark them as &amp;ldquo;processed&amp;rdquo; so you can exit your handler as quickly as possible and so not cause undue processing stress on your application and/or upstream service(s).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should wrap &lt;em&gt;potentially&lt;/em&gt; problematic code in a try/except (e.g. a function that makes HTTP requests can have multiple types of exceptions raised). Doing this means you can isolate that specific call and handle the failing scenarios appropriately.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;verify-your-message-handling-logic&#34;&gt;Verify your message handling logic&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You should understand the complete request flow of your message handling function(s) and be sure you are correctly dropping and/or re-queuing messages at the appropriate places within your application code. It’s very easy to not re-queue (or drop messages) by mistake.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When processing messages synchronously you typically just return &lt;code&gt;True&lt;/code&gt; (message was processed) or &lt;code&gt;False&lt;/code&gt; (requeue this message) from your handler. But in order to process messages asynchronously you need to call &lt;code&gt;nsq_msg.enable_async()&lt;/code&gt; and then you’ll need to make sure you explicitly return either &lt;code&gt;nsq_msg.finish()&lt;/code&gt; or &lt;code&gt;nsq_msg.requeue()&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;be-wary-of-global-variables&#34;&gt;Be wary of global variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most of the time global variables can be more performant as you&amp;rsquo;re reusing a pointer to some data, but there are some cases where a long-living (and large) global object (such as a &lt;a href=&#34;http://boto3.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;boto S3 connection&lt;/a&gt;) might end up leaking memory. This is something that should be measured and verified using the appropriate Python profiling tools first though.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;instrument-timers-around-your-primary-message-handler&#34;&gt;Instrument timers around your primary message handler&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to be able to identify anomalies in the performance of your message handlers. By using a decorator to time the function you can set up appropriate dashboards and alarms.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from your_metrics_abstraction import metrics&#xA;&#xA;@metrics.timed(&amp;quot;message_handler.time&amp;quot;)&#xA;async def message_handler(nsq_msg):&#xA;    ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;pynsq-doesn-t-support-coroutines&#34;&gt;Pynsq doesn’t support coroutines&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://github.com/nsqio/pynsq/issues/186&#34; target=&#34;_blank&#34;&gt;pynsq library only supports a ‘callback’ form of asynchronous message processing&lt;/a&gt;. Meaning if you were to define a message handler using a decorator like &lt;code&gt;@gen.coroutine&lt;/code&gt; or a native &lt;code&gt;async&lt;/code&gt; syntax (either one will convert the function into a coroutine) it will end up breaking the QR application by exiting the handler immediately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See the &lt;a href=&#34;#8&#34;&gt;next section&lt;/a&gt; for an example code snippet that works around this issue by utilising Tornado&amp;rsquo;s ioloop directly to schedule the handler’s asynchronous execution.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;prevent-messages-backing-up-in-the-queue&#34;&gt;Prevent messages backing up in the queue&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Messages can build up and cause alarms to fire if they are not pulled from the queue and successfully processed by your application in a timely fashion. You can help resolve this by either configuring the &lt;a href=&#34;http://pynsq.readthedocs.io/en/latest/reader.html&#34; target=&#34;_blank&#34;&gt;nsq.Reader#max_in_flight&lt;/a&gt; attribute and/or processing your messages asynchronously.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from tornado import ioloop&#xA;&#xA;async def coro_handler(msg):&#xA;    # ... do stuff&#xA;    return msg.finish()&#xA;&#xA;def handler(msg):&#xA;    msg.enable_async()&#xA;    ioloop.IOLoop.current().add_callback(coro_handler, msg)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also look to tweak the &lt;a href=&#34;http://pynsq.readthedocs.io/en/latest/reader.html&#34; target=&#34;_blank&#34;&gt;nsq.Reader#max_tries&lt;/a&gt; attribute, which defines the number of times a message can be requeued before it is permanently dropped (this prevents cyclic errors).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is also the &lt;a href=&#34;http://pynsq.readthedocs.io/en/latest/message.html#nsq.Message.touch&#34; target=&#34;_blank&#34;&gt;nsq.Message#touch&lt;/a&gt; method which lets you indicate to the NSQ daemon that you need more time to process the message and thus postpone (for a little while at least) the message processing from timing out and being automatically re-queued (depending on the setting of the &lt;code&gt;max_tries&lt;/code&gt; attribute).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;avoid-api-libraries-auto-retrying-expensive-operations&#34;&gt;Avoid API libraries auto-retrying expensive operations&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some API libraries, such as &lt;a href=&#34;http://boto3.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;boto&lt;/a&gt;, allow you to configure it so that operations are retried N number of times before finally failing. This can be helpful to ensure a temporary network blip or error doesn&amp;rsquo;t cause a message to be unnecessarily dropped or requeued. But this can also bring a performance overhead if the operation in question is very slow. Review the API calls you are making and evaluate how expensive they are. In some cases you might prefer to configure &amp;ldquo;retries&amp;rdquo; off and have NSQ handle these temporary errors (i.e. by re-queuing messages).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of how to configure boto to not retry operations:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;s3_resource = session.resource(&amp;quot;s3&amp;quot;, config=Config(&#xA;    connect_timeout=2, &#xA;    read_timeout=2,&#xA;    retries={&#39;max_attempts&#39;: 0}&#xA;  )&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as per the example above, it’s worth tweaking the connection/read timeouts as well. For example we noticed that calls for &lt;code&gt;.xml&lt;/code&gt; files from S3 were really slow and so in that service we had to increase the &lt;code&gt;read_connection&lt;/code&gt; by a significant amount (but not too much; you don’t want the client to sit hanging for a long period of time, so it requires some fine tuning to get it right).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;place-blocking-io-operations-into-a-thread-pool&#34;&gt;Place blocking IO operations into a thread pool&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some libraries do not provide asynchronous support (such as &lt;a href=&#34;https://redis-py.readthedocs.io/en/latest/&#34; target=&#34;_blank&#34;&gt;Python&amp;rsquo;s redis library&lt;/a&gt;). So if your message handler is asynchronous, and you’re also executing a potentially long running &lt;em&gt;blocking&lt;/em&gt; operation (such as an S3 object GET), then this will end up causing your application to block the ioloop and prevent concurrently handling multiple messages.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from app.threadpool import run_on_executor&#xA;&#xA;async def message_handler():&#xA;    result = await run_on_executor(fn, arg1, arg2, ...)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then the &lt;code&gt;app.threadpool&lt;/code&gt; referenced in the above snippet would look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from tornado import gen&#xA;from concurrent.futures import ThreadPoolExecutor&#xA;&#xA;from bf_rig import settings&#xA;&#xA;&#xA;THREAD_POOL = ThreadPoolExecutor(settings.get(&#39;pool_max_workers&#39;))  # 10&#xA;&#xA;&#xA;@gen.coroutine&#xA;def run_on_executor(*args, **kwargs):&#xA;    result = yield THREAD_POOL.submit(*args, **kwargs)&#xA;    raise gen.Return(result)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above example needs to use a Tornado decorator as &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; doesn&amp;rsquo;t work with native coroutines. It would require the use of &lt;code&gt;asyncio.wrap_future&lt;/code&gt; which isn&amp;rsquo;t much better than just using Tornado&amp;rsquo;s own decorator.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; will only help you deal with IO bound tasks that need to be handled asynchronously (and whose library doesn&amp;rsquo;t support natively). If the task to be executed is actually CPU bound then you&amp;rsquo;ll want to utilise a &lt;a href=&#34;https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;ProcessPoolExecutor&lt;/code&gt;&lt;/a&gt; instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;rate-limit-yourself&#34;&gt;Rate limit yourself&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In a service where there&amp;rsquo;s a potential for lots of duplicate messages it can be useful to implement some simple rate limiting logic. In one of our QR services we use Redis to track duplicate requests and then execute some basic rate limiting logic in order to prevent overwhelming any upstream services that would otherwise be called.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be aware that the rate limit you set can cause unwanted side-effects. For example, if you start to requeue messages during a rate limit period, you may start to see that messages aren&amp;rsquo;t being processed quickly enough and so the queue depth will begin to increase (i.e. the queue will start to backup and fill up) and this might cause monitors (e.g. systems like Datadog/Nagios) to trigger.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;disable-yourself&#34;&gt;Disable yourself&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider your upstream services and identify if there&amp;rsquo;s ever a point where your service needs to stop making requests to it. Most services will be sat behind an API Gateway so they&amp;rsquo;ll likely &lt;em&gt;enforce&lt;/em&gt; rate limiting on &lt;em&gt;you&lt;/em&gt;. But that might not always be the case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One example of this is a QR service which makes requests to a separate rendering service for HTML content to be backed up into AWS S3. There are periods where this rendering service will dynamically purge its cache (both its internal application cache, and also the outer CDN cache layer). In order to prevent the QR service from overloading the rendering service during this period where it&amp;rsquo;s vulnerable(†), we automatically disable the QR service (we use a shared redis cluster to identify the switch in a key value; so we change it from disabled to enabled).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† due to it having no cache! none of these services we have are vulnerable in the security sense, as they&amp;rsquo;re internal access only within a VPC&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The below example demonstrates an implementation used in one of our QR services, which was to use a Python decorator:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from app.foo import toggle&#xA;&#xA;@toggle(&#39;status&#39;)&#xA;def _message_handler(nsq_msg, *args, **kwargs):&#xA;    nsq_msg.enable_async()&#xA;    ioloop.IOLoop.current().add_callback(message_handler, nsq_msg)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;app.foo&lt;/code&gt; code then looked something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def toggle_qr(status_key: str) -&amp;gt; Callable:&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    When status_key is set to &#39;stopped&#39; in redis, &#xA;    this decorator will finish the nsq message and return immediately, &#xA;    otherwise it will proceed with event handling.&#xA;&#xA;    Arguments:&#xA;        status: name of the status key in redis.&#xA;    Returns:&#xA;        Wrapped message handler.&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    def deco(function):&#xA;        @wraps(function)&#xA;        def wrapper(nsq_msg: Message, *args, **kwargs):&#xA;            assert &#39;redis&#39; in kwargs, &#39;redis parameter is required&#39;&#xA;            redis = kwargs[&#39;redis&#39;]&#xA;            try:&#xA;                status = redis.get(status_key)&#xA;            except Exception as e:&#xA;                status = None&#xA;            if status == b&#39;stopped&#39;:&#xA;                nsq_msg.finish()&#xA;                return&#xA;            return function(nsq_msg, *args, **kwargs)&#xA;        return wrapper&#xA;    return deco&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;drop-or-requeue&#34;&gt;Drop or Requeue?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider the previous section about disabling a QR service in times where it might be necessary to protect an upstream (e.g. where rate limiting yourself maybe doesn&amp;rsquo;t make sense, or being rate limited by the upstream isn&amp;rsquo;t possible), you might then need to make a decision about what you do with the messages that are building up in the message queue.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Those messages will eventually reach a threshold and in some cases it might make more sense to not requeue messages while the QR service is in &amp;lsquo;disable&amp;rsquo; mode, but instead just drop them completely. The answer, and your approach, will depend on the message source itself: are they messages that you can afford to drop? are they generated fairly regularly?&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/queue-best-practices/</guid>
      <link>https://www.integralist.co.uk/posts/queue-best-practices/</link>
      <pubDate>Sun, 26 Nov 2017 00:00:00 +0000</pubDate>
      <title>NSQ Queue Reader Best Practices</title>
    </item>
    <item>
      <description>&lt;p&gt;This post aims to discuss key monitoring discussion points and to summarise the relevant best practices when instrumenting application performance monitoring.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some of the areas we&amp;rsquo;ll be focusing in on&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#terminology&#34;&gt;Terminology&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#understand-the-different-types-of-monitoring&#34;&gt;Understand the different types of monitoring&lt;/a&gt;.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#data-collection-methods&#34;&gt;Data collection methods&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#frontend-monitoring&#34;&gt;Frontend monitoring&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#make-it-useful-then-actionable&#34;&gt;Make it useful, then actionable&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#focus-on-user-impact&#34;&gt;Focus on user impact&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#favour-organic-changes-over-static-thresholds&#34;&gt;Favour organic changes over static thresholds&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#send-critical-and-noncritical-alarms-to-different-channels&#34;&gt;Send critical and noncritical alarms to different channels&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#give-context&#34;&gt;Give context&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#think-about-data-aggregation&#34;&gt;Think about data aggregation&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#know-your-graphs&#34;&gt;Know your graphs&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#map-your-graphs&#34;&gt;Map your graphs&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#choosing-between-a-metric-or-log&#34;&gt;Choosing between a metric or log&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;#reference-material&#34;&gt;Reference material&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we primarily work with &lt;a href=&#34;https://www.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt; so you&amp;rsquo;ll see them mentioned a lot throughout this post.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There is a lot of confusion around the difference between certain terms such as &amp;ldquo;observability&amp;rdquo;, &amp;ldquo;monitoring&amp;rdquo;, &amp;ldquo;instrumentation&amp;rdquo; and &amp;ldquo;telemetry&amp;rdquo;. Let&amp;rsquo;s start with defining what each of these mean&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;u&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/u&gt; is a measure of how well internal states of a system can be inferred from knowledge of its external outputs – Wikipedia&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In that context, &amp;ldquo;observability&amp;rdquo; is the word you use when talking about how well your systems are doing in a broad overarching sense (is the system &lt;em&gt;observable&lt;/em&gt;?). Beneath the umbrella term &amp;ldquo;observability&amp;rdquo; we&amp;rsquo;ll then find &amp;ldquo;monitoring&amp;rdquo; and &amp;ldquo;instrumentation&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;u&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/u&gt; is the translation of IT metrics into business meaning – Wikipedia&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In that context, &amp;ldquo;monitoring&amp;rdquo; is the word you use when talking about tools for viewing data that has been recorded by your systems (whether that be time series data, or logging etc). These monitoring tools are supposed to help you identify both the &amp;ldquo;what&amp;rdquo; and the &amp;ldquo;why&amp;rdquo; something has gone wrong.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;u&gt;&lt;strong&gt;Instrumentation&lt;/strong&gt;&lt;/u&gt; refers to an ability to monitor or measure the level of a product&amp;rsquo;s performance, to diagnose errors and to write trace information – Wikipedia&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In that context, &amp;ldquo;instrumentation&amp;rdquo; is the word you use when talking about how you&amp;rsquo;re recording data to be viewed and monitored.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;u&gt;&lt;strong&gt;Telemetry&lt;/strong&gt;&lt;/u&gt; is the process of gathering remote information that is collected by instrumentation – MSDN&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In that context, &amp;ldquo;telemetry&amp;rdquo; is the word you use when talking about the mechanisms for &lt;em&gt;acquiring&lt;/em&gt; the data that has been &lt;em&gt;gathered&lt;/em&gt; by your instrumentation (e.g. tools like &lt;a href=&#34;https://www.fluentd.org/&#34; target=&#34;_blank&#34;&gt;FluentD&lt;/a&gt; or &lt;a href=&#34;https://en.wikipedia.org/wiki/Syslog&#34; target=&#34;_blank&#34;&gt;Syslog&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understand-the-different-types-of-monitoring&#34;&gt;Understand the different types of monitoring&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Although most of this document is based around one specific type of monitoring (&lt;a href=&#34;https://en.wikipedia.org/wiki/Application_performance_management&#34; target=&#34;_blank&#34;&gt;APM&lt;/a&gt;), it&amp;rsquo;s good to be aware of the various types of monitoring available across an entire system.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server monitoring&lt;/strong&gt;:&lt;br&gt;&#xA;monitor the health of your servers and ensure they stay operating efficiently.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration change monitoring&lt;/strong&gt;:&lt;br&gt;&#xA;monitor your system configuration to identify if and when changes to your infrastructure impact your application.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application performance monitoring&lt;/strong&gt;:&lt;br&gt;&#xA;look inside your application and services to make sure they are operating as expected (also known as APM tooling).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Synthetic testing&lt;/strong&gt;:&lt;br&gt;&#xA;real time interactions to verify how your application is functioning from the perspective of your users (hopefully to catch errors before they do).&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alerting&lt;/strong&gt;:&lt;br&gt;&#xA;notify the service owners when problems occur so they can resolve them, minimizing the impact to your customers.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;data-collection-methods&#34;&gt;Data collection methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are fundamentally two methods for data collection:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Push&lt;/strong&gt;: sending metrics to an analysis tool.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Pull&lt;/strong&gt;: configuring a health check endpoint, that a centralised tool pulls data from.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;When dealing with the &amp;lsquo;pull&amp;rsquo; model you&amp;rsquo;ll hear people suggest that rather than a simple &amp;lsquo;200 OK&amp;rsquo; response you should add extra information that gives &lt;em&gt;humans&lt;/em&gt; more understanding of the overall state of the service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So this could be things like a successful database connection was opened. But a possible concern would be the performance overhead that might need to be accounted for (remember: health endpoints are generally pinged every few minutes).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are also various metric &lt;em&gt;types&lt;/em&gt; you can collect data as. Two common ones are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Counter&lt;/strong&gt;: an ever increasing value.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Gauge&lt;/strong&gt;: a point-in-time value (can arbitrarily go up and down).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Histogram&lt;/strong&gt;: samples observations and counts them in configurable buckets.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Histograms might require a little extra clarification: they sample observations (e.g. request durations) and count different perspectives on the data. In the case of &amp;lsquo;request duration&amp;rsquo; you&amp;rsquo;d likely see the different &amp;lsquo;perspectives&amp;rsquo; being: count, avg, median, max and 95percentile.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;For more information, see these Datadog articles: &lt;a href=&#34;https://docs.datadoghq.com/metrictypes/&#34; target=&#34;_blank&#34;&gt;Metric Types&lt;/a&gt; and &lt;a href=&#34;https://docs.datadoghq.com/guides/dogstatsd/&#34; target=&#34;_blank&#34;&gt;DogStatsD&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;frontend-monitoring&#34;&gt;Frontend monitoring&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two main approaches to frontend monitoring:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Real User Monitoring (RUM).&lt;/li&gt;&#xA;&lt;li&gt;Synthetic.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The difference between them has to do with the &lt;em&gt;type&lt;/em&gt; of traffic that is triggering the data collection. For example, with RUM the requests being processed are from &lt;em&gt;real users&lt;/em&gt;, whereas with synthetic monitoring the requests are fake (i.e. they are generated by your own software).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Synthetic monitoring causes data to be collected for analysis, thus allowing you to identify the availability and performance of your system by constructing very specific test cases.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;make-it-useful-then-actionable&#34;&gt;Make it useful, then actionable&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start with a quote from Charity Majors (author of &lt;a href=&#34;http://shop.oreilly.com/product/0636920039761.do&#34; target=&#34;_blank&#34;&gt;Database Reliability Engineering&lt;/a&gt; and CEO of &lt;a href=&#34;http://honeycomb.io/&#34; target=&#34;_blank&#34;&gt;honeycomb.io&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;u&gt;&lt;strong&gt;Don&amp;rsquo;t attempt to &amp;ldquo;monitor everything&amp;rdquo;&lt;/strong&gt;&lt;/u&gt;. You can&amp;rsquo;t. Engineers often waste so much time doing this that they lose track of the critical path, &lt;u&gt;&lt;strong&gt;and their important alerts drown in fluff and cruft&lt;/strong&gt;&lt;/u&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;When a monitor triggers an alarm, it should first and foremost be &amp;ldquo;useful&amp;rdquo;. Secondly, it should be &amp;ldquo;actionable&amp;rdquo;. There should be something you can do to resolve the alarm and also be a set of steps (post-resolution) to prevent that alarm from triggering again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the alarm isn&amp;rsquo;t &lt;em&gt;actionable&lt;/em&gt;, then it just becomes noise.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;focus-on-user-impact&#34;&gt;Focus on user impact&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is a quote from Mike Julian (author of &lt;a href=&#34;http://shop.oreilly.com/product/0636920050773.do&#34; target=&#34;_blank&#34;&gt;Practical Monitoring&lt;/a&gt; and &lt;a href=&#34;https://weekly.monitoring.love&#34; target=&#34;_blank&#34;&gt;Monitoring Weekly&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Go as deep and wide with your instrumentation as you want, but always be asking yourself, &amp;ldquo;&lt;u&gt;&lt;strong&gt;How will these metrics show me the user impact?&lt;/strong&gt;&lt;/u&gt;&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Or put another way: &amp;ldquo;Who is your &lt;em&gt;customer&lt;/em&gt;&amp;rdquo;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Depending on the services you build, your customers might be people who pay money to use your service, or they might be other engineers within your organisation who are consuming an API you&amp;rsquo;ve developed. Either way, your customer is the most important thing to you and your service. You need to keep them happy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For most users, whether they be a non-technical paying customer or an engineer, they will have certain criteria that will make them happy. You could imagine the sorts of questions they&amp;rsquo;ll ask to be something like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want the service to work as expected&lt;/strong&gt;&lt;br&gt;&#xA;i.e. you should monitor whatever is determined to be a &amp;lsquo;success rate&amp;rsquo; for your service.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want the service to be fast&lt;/strong&gt;&lt;br&gt;&#xA;i.e. you should monitor the service latency.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want to use &amp;lsquo;this much&amp;rsquo; of the service&lt;/strong&gt;&lt;br&gt;&#xA;i.e. you should monitor things like &amp;lsquo;requests per second&amp;rsquo; - do you have &lt;a href=&#34;https://en.wikipedia.org/wiki/Service-level_agreement&#34; target=&#34;_blank&#34;&gt;SLA&lt;/a&gt;&amp;rsquo;s defined?&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;In essence you should start by creating monitors for things that have a &lt;em&gt;direct impact&lt;/em&gt; on your users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, measuring OS level metrics such as CPU and memory consumption is great for diagnostics &amp;amp; performance analysis, as they help to highlight the underlying system behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you should probably not be using these stats for alarming, as their values can have relative meaning in different situations and they don&amp;rsquo;t necessarily offer much in the way of understanding the &lt;em&gt;root cause&lt;/em&gt; of the problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead, try monitoring 5xx errors and very slow latency times. These metrics are much more useful indicators of problems with the system and real negative user experiences.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately, the deeper you go, the more specific your alarms become, and the less useful they are at identifying trends and patterns.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;favour-organic-changes-over-static-thresholds&#34;&gt;Favour organic changes over static thresholds&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Static thresholds such as &amp;ldquo;the number of errors reported has exceeded N&amp;rdquo; have a habit of raising false alarms, due typically to unexpected spikes in data (anomalies).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This happens so frequently that most monitoring tools/services (such as nagios) offer &amp;ldquo;flapping detection&amp;rdquo; to help prevent these deviations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To help with this services such as &lt;a href=&#34;https://www.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt; offer a feature called &amp;ldquo;&lt;a href=&#34;https://www.datadoghq.com/blog/introducing-recovery-thresholds/&#34; target=&#34;_blank&#34;&gt;recovery thresholds&lt;/a&gt;&amp;rdquo; which helps to quieten monitor state changes so you can be confident when a monitor switches back to OK state that it has in fact definitely resolved itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way it works is like so: you give Datadog a threshold value that must be met to consider the monitor “back to normal”. Once the monitor state switches to ALARM it will now never flip-flop between OK and ALARM. It will only ever go back to OK if the set recovery threshold goes below the specified value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They also offer &amp;ldquo;&lt;a href=&#34;https://docs.datadoghq.com/guides/anomalies/&#34; target=&#34;_blank&#34;&gt;anomaly detection&lt;/a&gt;&amp;rdquo;, which detects when a metric is behaving differently than it has in the past, taking into account trends, seasonal day-of-week and time-of-day patterns. This can be more useful for organically identifying issues, as it allows for buffer zones around your static thresholds.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Datadog also offers &amp;ldquo;&lt;a href=&#34;https://docs.datadoghq.com/guides/outliers/&#34; target=&#34;_blank&#34;&gt;outlier monitoring&lt;/a&gt;&amp;rdquo; which detects when a specific member of a group (e.g., hosts, availability zones, partitions) is behaving unusually compared to the rest. They are useful for noticing when a given group, which should behave uniformly, isn&amp;rsquo;t doing so.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;A summary of Datadog&amp;rsquo;s various detection methods can be found &lt;a href=&#34;https://docs.datadoghq.com/guides/monitors/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;send-critical-and-noncritical-alarms-to-different-channels&#34;&gt;Send critical and noncritical alarms to different channels&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At BuzzFeed I work in the software infrastructure team and there we have two separate Slack channels for handling monitoring notifications:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;#oo-infra-alarms&lt;/li&gt;&#xA;&lt;li&gt;#oo-infra-warnings&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Only alarms that require immediate review (such as a 5xx monitor) goes into #oo-infra-alarms. Everything else is sent to #oo-infra-warnings because although important, they aren&amp;rsquo;t surfacing immediately as user issues.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t do this, then you&amp;rsquo;ll find people become fatigued by the sheer amount of noise coming from multiple alarms. Especially alarms that are firing due to unactionable anomalies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To quote (again) Charity Majors&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In the chaotic future we&amp;rsquo;re all hurtling toward, you need the discipline to &lt;u&gt;&lt;strong&gt;have radically fewer paging alerts - not more&lt;/strong&gt;&lt;/u&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You should also consider sending a monitor&amp;rsquo;s &amp;ldquo;warning&amp;rdquo; state to a different channel for similar reasons. You can define different channels in Datadog using the following template code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{{#is_alert}}&#xA;@slack-my-channel-for-serious-alarms&#xA;{{/is_alert}}&#xA;&#xA;{{#is_warning}}&#xA;@slack-my-channel-for-just-warnings-to-keep-an-eye-on&#xA;{{/is_warning}}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;give-context&#34;&gt;Give context&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When an monitor triggers an alarm, and you&amp;rsquo;re on-call that night, then you might be unfamiliar with the system and its dependencies. One quick way to help people on-call is to provide them with additional context about the alarm and the affected system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A general message template could look something like the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;Alarm Title&amp;gt;&#xA;&amp;lt;Alarm Summary&amp;gt;&#xA;&amp;lt;Concise service description&amp;gt;&#xA;&amp;lt;Monitoring links&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An example might look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Foo-Service 5xx&#xA;&#xA;Foo-Service is serving a high number of 5xx responses, &#xA;these will not be cached at CDN, possibly resulting in further cache misses.&#xA;&#xA;Foo-Service serves responsive article pages for the BuzzFeed website (www.buzzfeed.com) &#xA;and is fronted by a CDN. It has an upstream dependency on Redis and the internal Buzz API v2.&#xA;&#xA;Please refer to the monitoring for more details:&#xA;&#xA;- Logs&#xA;- Dashboard&#xA;- Timeboard&#xA;- Request Breakdown&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alarms highlight the symptom and not the cause. So if at all possible, try to include information or data that might aid the on-call person in identifying the root cause of the issue.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;think-about-data-aggregation&#34;&gt;Think about data aggregation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with TSDB&amp;rsquo;s (&lt;a href=&#34;https://en.wikipedia.org/wiki/Time_series_database&#34; target=&#34;_blank&#34;&gt;Time Series Database&lt;/a&gt;) you&amp;rsquo;ll find they will start aggregating multiple data points into a single data point. This is known as the &amp;ldquo;roll up&amp;rdquo; effect.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you weren&amp;rsquo;t aware, a TSDB is made up of key/value pairs. The key is the timestamp and the value is the metric value at that point in time.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The problem with &amp;lsquo;rolling up&amp;rsquo; data is that it &lt;em&gt;smooths&lt;/em&gt; out your data points. Meaning you shift from a graph that has lots of spikes (i.e. a graph that shows every possible false positive), to a graph that covers up those false positive spikes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the plus side, rolling up data like this means you get to see the data at a higher level and so &lt;em&gt;patterns&lt;/em&gt; of use start to emerge.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There have been examples in the past where &lt;em&gt;important&lt;/em&gt; spikes in CPU/Memory were not captured due to the smoothing out of aggregated data and so it can be useful to look at your data closely (at first) and then in some instances force the disabling of rolling up data using Datadog&amp;rsquo;s &lt;code&gt;.rollup()&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately, you&amp;rsquo;ll need to find the balance that works best for you and your monitoring requirements.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can read more about this smoothing out process &lt;a href=&#34;https://help.datadoghq.com/hc/en-us/articles/203571289-Why-does-zooming-out-a-timeframe-also-smooth-out-my-graphs-&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;, as well as the &lt;code&gt;.rollup()&lt;/code&gt; method Datadog provides to allow you to control this behaviour.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;know-your-graphs&#34;&gt;Know your graphs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We won&amp;rsquo;t repeat the details here, but suffice to say, each graph in Datadog has a purpose and specialised use case. You should review Datadog&amp;rsquo;s articles on the various graphs they offer and the whys/when of using them:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.datadoghq.com/blog/timeseries-metric-graphs-101/&#34; target=&#34;_blank&#34;&gt;Timeseries graphs&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.datadoghq.com/blog/summary-graphs-metric-graphs-101/&#34; target=&#34;_blank&#34;&gt;Summary graphs&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;update&#34;&gt;UPDATE&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve since written a blog post about stastistics (aimed at beginners) and so by understanding the basics of statistics you&amp;rsquo;ll be able to understand more clearly what certain graphs represent and how.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can read the post here: &lt;a href=&#34;/posts/statistics-basics/&#34;&gt;Statistics and Graphs: The Basics&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;map-your-graphs&#34;&gt;Map your graphs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be useful to order your graphs (within a dashboard/timeboard) &lt;em&gt;chronologically&lt;/em&gt;. For example, CDN -&amp;gt; LB -&amp;gt; Service. This can help you mentally model the request flow through your system, such that you know the request starts by hitting your CDN layer, it&amp;rsquo;s then routed inside of your infrastructure and hits a load balancer, finally that load balancer distributes the request to a specific service node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can equally be useful to collate multiple services (and their graphs) within a single overarching dashboard, because when there is a problem in the system you can follow the request flow from start to finish and see where a bottleneck (or anomaly) somewhere else in the chain is causing a side effect elsewhere in the chain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An alternative approach is to have a dashboard that focuses on the key metrics for a service&amp;rsquo;s performance, and underneath that they&amp;rsquo;ll have graphs that monitor their dependencies. So when an engineer gets a call because of an issue that seems to be with their service, they&amp;rsquo;ll check the dashboard and might see there&amp;rsquo;s an issue upstream of them with one of their dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some companies even take that approach a step further and formalize this process and subsequently define a standardized structure for dashboards (i.e. all dashboards are structurally the same). The benefit of that approach is that people on-call can start at the beginning of a request and then follow the dashboards like a thread until they reach a service that is the root cause of the problem being reported.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;choosing-between-a-metric-or-log&#34;&gt;Choosing between a metric or log&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order to help individual teams identify whether they should collect data as a metric or as a log, one recommended approach is to ask the following questions:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Is it easier for your team to &lt;em&gt;think&lt;/em&gt; about metrics or logs?&lt;/li&gt;&#xA;&lt;li&gt;Is it more &lt;em&gt;effective&lt;/em&gt; for the thing in question to be a log entry or metric?&lt;/li&gt;&#xA;&lt;li&gt;What questions do you typically ask &lt;em&gt;when debugging&lt;/em&gt;?&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;We can&amp;rsquo;t answer these questions for you, but we have generally found the following approach works reasonably well as a generic pattern (&lt;a href=&#34;https://dictionary.cambridge.org/dictionary/english/ymmv&#34; target=&#34;_blank&#34;&gt;YMMV&lt;/a&gt;)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Collect an exception as &lt;em&gt;both&lt;/em&gt; a log and an error.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The log helps add additional context not available in the metric.&lt;/li&gt;&#xA;&lt;li&gt;The metric helps with monitoring and triggering alarms.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Log &lt;em&gt;only&lt;/em&gt; errors/exceptions.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&amp;ldquo;No news is good news&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Control other log calls using &lt;a href=&#34;/posts/logging-101/&#34;&gt;log levels&lt;/a&gt; (so they can be enabled when necessary).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Include unique identifiers with your logs&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This helps to quickly figure out what the log is possibly associated with when looking from a centralized distributed log system which contains many logs aggregated from many distinct services.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Mostly everything else we&amp;rsquo;ll record as a metric so we can monitor pattern changes.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;other-useful-tips&#34;&gt;Other useful tips&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.datadoghq.com/guides/tagging/&#34; target=&#34;_blank&#34;&gt;Datadog tags&lt;/a&gt; are useful for splitting metrics by type (e.g. status codes).&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.datadoghq.com/api/#events-post&#34; target=&#34;_blank&#34;&gt;Datadog events&lt;/a&gt;, are useful for capturing additional info (e.g. exception message).&lt;/li&gt;&#xA;&lt;li&gt;99% of the time you want a &lt;a href=&#34;https://help.datadoghq.com/hc/en-us/articles/204580349-What-is-the-difference-between-a-ScreenBoard-and-a-TimeBoard-&#34; target=&#34;_blank&#34;&gt;Timeboard, &lt;em&gt;not&lt;/em&gt; a Screenboard&lt;/a&gt;.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Timeboards allow for tracking data points across multiple graphs at once.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Let people know where the dashboards are, Slack pinned, Runbooks etc&lt;/li&gt;&#xA;&lt;li&gt;For latency use &lt;a href=&#34;https://en.wikipedia.org/wiki/68%E2%80%9395%E2%80%9399.7_rule&#34; target=&#34;_blank&#34;&gt;95th percentile (standard deviation)&lt;/a&gt;, not just the &amp;lsquo;mean average&amp;rsquo;.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Because the mean can miss important slow requests.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Load balancer metrics can also be useful to monitor (especially if service is falling over).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-material&#34;&gt;Reference material&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920050773.do&#34; target=&#34;_blank&#34;&gt;Practical Monitoring: Effective Strategies for the Real World&lt;/a&gt; (book)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.infoq.com/articles/charity-majors-observability-failure&#34; target=&#34;_blank&#34;&gt;Observability and Understanding the Operational Ramifications of a System.&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.datadoghq.com/blog/timeseries-metric-graphs-101/&#34; target=&#34;_blank&#34;&gt;Datadog: Timeseries graphs.&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.datadoghq.com/blog/summary-graphs-metric-graphs-101/&#34; target=&#34;_blank&#34;&gt;Datadog: Summary graphs.&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/monitoring-best-practices/</guid>
      <link>https://www.integralist.co.uk/posts/monitoring-best-practices/</link>
      <pubDate>Wed, 15 Nov 2017 00:00:00 +0000</pubDate>
      <title>Observability and Monitoring Best Practices</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post should serve as a guideline for running load tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is designed to be a concise list of notes and tips.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For a list of load testing tools, including their reviews and benchmark results, I refer you to the &amp;ldquo;&lt;a href=&#34;#15&#34;&gt;Tools&lt;/a&gt;&amp;rdquo; section at the end.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;use-real-datasets&#34;&gt;Use real datasets&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Parse your access logs for real user requests, then replay those requests within your load test. Also be mindful of different time periods for more accurate distribution of transactions. Look for realistic worst case situations (there may be more than one).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;identify-collateral-damage&#34;&gt;Identify collateral damage&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What users or upstreams will be affected by this additional load?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Are there any vulnerable dependencies that should be: notified of the load test or protected from it? † (&lt;a href=&#34;#4&#34;&gt;see next section&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† not all services are completely isolated. Consider what happens when your services is using an external API service. If the API is doing its job right it should start rate limiting you (or denies you access for exceeding your thresholds). But that still doesn&amp;rsquo;t necessarily mean you have to be a bad web citizen and start hammering their service (on a side note: you should probably be considering caching).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;stub-services-if-necessary&#34;&gt;Stub services if necessary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Rather than hit a real upstream, try creating a mock version. The benefit of doing this is that you can your mock service to allow for controlling the latency and/or throughput restraints (thus mimicking different failure scenarios and seeing how your service behaves under different conditions).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;distribute-your-traffic&#34;&gt;Distribute your traffic&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When your service response is fairly big, it’s easy to hit a network capacity limit, so if you’re seeing that your service doesn’t scale with addition of new instances, this may be the root cause. To help avoid this, use &lt;a href=&#34;https://github.com/tsenart/vegeta#usage-distributed-attacks&#34; target=&#34;_blank&#34;&gt;distributed testing&lt;/a&gt; (here&amp;rsquo;s an example &lt;a href=&#34;https://gist.github.com/Integralist/e4b4e53dd09745b645e10e89fc133f63&#34; target=&#34;_blank&#34;&gt;wrapper&lt;/a&gt; to simplify the process).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;automate-for-reproducible-runs&#34;&gt;Automate for reproducible runs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Write simple scripts that let you coordinate a fresh load test run. Such as configuring mock services and defining specific strategies (e.g. running a &amp;lsquo;&lt;a href=&#34;https://en.wikipedia.org/wiki/Soak_testing&#34; target=&#34;_blank&#34;&gt;soak&lt;/a&gt;&amp;rsquo; test vs. a shorter duration load test that mimicks a slow ramp-up in traffic pattern vs a load test that mimicks a &amp;lsquo;thundering herd&amp;rsquo; approach).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;consider-disabling-authentication&#34;&gt;Consider disabling authentication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be hard to include auth tokens/keys in load testing tools, and as such it is often easier to use a network secured backend and a custom code branch that either allows for auth bypass or has no authentication.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although being able to load test with authentication is important as it could highlight important problem points in your architecture design.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;don-t-immediately-scale-dependencies&#34;&gt;Don&amp;rsquo;t immediately scale dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have a dependency such as redis (or another type of data store), then leave it configured to the size it currently is. If you have a stage environment, it can be tempting to configure that stage resource to be identical to your production environment. But it would be better to first verify if that resource is even a problem point by analysing the results of an initial load test with all resources configured normally for that environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you&amp;rsquo;ve run your load test, if you find you&amp;rsquo;re having no issues, then sure you &lt;em&gt;could&lt;/em&gt; consider increasing/scaling up the resource in question. But ultimately if it wasn&amp;rsquo;t a problem before, then it is unlikely to be an issue once it has even more compute/memory/network/etc.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;send-traffic-from-different-geographical-regions&#34;&gt;Send traffic from different geographical regions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be beneficial to set-up load testing instances in multiple &lt;a href=&#34;http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html&#34; target=&#34;_blank&#34;&gt;regions and availability zones&lt;/a&gt;. This is ideal for a highly dynamic application expected to be globally utilized, as it means you can accurately simulate traffic with different latency expectations. Although, if you have a simple/static application, maybe the use of &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;CDN edge caching&lt;/a&gt; is enough to mitigate concern.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;decide-if-your-tool-should-support-reusing-connections&#34;&gt;Decide if your tool should support reusing connections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A tool such as &lt;a href=&#34;https://github.com/JoeDog/siege&#34; target=&#34;_blank&#34;&gt;Siege&lt;/a&gt; doesn’t support reusing existing http connections. This can be interesting as far as identifying how your system behaves under those conditions. But reusing existing connections is mostly preferred so that throughput can be properly verified. Tools such as &lt;a href=&#34;https://github.com/tsenart/vegeta&#34; target=&#34;_blank&#34;&gt;Vegeta&lt;/a&gt; and &lt;a href=&#34;https://github.com/wg/wrk&#34; target=&#34;_blank&#34;&gt;Wrk&lt;/a&gt; support connection reuse and have better performance/features.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;start-testing-a-single-instance-before-moving-onto-clusters&#34;&gt;Start testing a single instance, before moving onto clusters&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We should ideally identify the threshold of a single instance before moving onto testing a cluster of instances. This is so that we can make appropriate tweaks to our application(s) based on the initial load testing results and should then help improve the initial cluster results as well.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;verify-load-using-multiple-strategies&#34;&gt;Verify load using multiple strategies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are multiple types of load testing strategies: constant, ramp-up, soak test (and more). Research and identify which is the most appropriate for your service under test. It may be that you’ll want to execute multiple strategies.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reset-your-environment-between-test-runs&#34;&gt;Reset your environment between test runs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Ensure your system is back to &amp;lsquo;normal&amp;rsquo; (that means different things to different services) before starting another load test. Otherwise your test results will be skewed by the system being in a &amp;lsquo;hot&amp;rsquo; state and could also mean putting your upstream services under &lt;a href=&#34;https://en.wikipedia.org/wiki/Denial-of-service_attack&#34; target=&#34;_blank&#34;&gt;DoS&lt;/a&gt; like scenarios.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;document-the-results&#34;&gt;Document the results&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It is beneficial for all (i.e. your team and others) to be able to review the load test results. Ensure each test is documented in a consistent, known and obvious location. For example, store them in a &lt;code&gt;/docs/load-tests&lt;/code&gt; folder inside your service code base and include any key fixes (e.g. changes made that resolved a problem in your service performance).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tools&#34;&gt;Tools&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are various load/stress testing tools available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following, for me, are the top three open-source choices:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.joedog.org/siege-home/&#34; target=&#34;_blank&#34;&gt;Siege&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/tsenart/vegeta&#34; target=&#34;_blank&#34;&gt;Vegeta&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/wg/wrk&#34; target=&#34;_blank&#34;&gt;Wrk&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For a review of these tools (and many more open-source options), please read:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://blog.loadimpact.com/open-source-load-testing-tool-review&#34; target=&#34;_blank&#34;&gt;Load Testing Tools Review&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://blog.loadimpact.com/open-source-load-testing-tool-benchmarks&#34; target=&#34;_blank&#34;&gt;Load Testing Tools Benchmarks&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/load-testing-guidelines/</guid>
      <link>https://www.integralist.co.uk/posts/load-testing-guidelines/</link>
      <pubDate>Mon, 13 Nov 2017 00:00:00 +0000</pubDate>
      <title>Load Testing Guidelines</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;logs&#34;&gt;Logs?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Applications should record information/events to help make debugging (and understanding) what a program is doing easier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically this information is recorded into a &lt;a href=&#34;https://en.wikipedia.org/wiki/Log_file&#34; target=&#34;_blank&#34;&gt;log file&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in some cases it is preferred to send this information to &lt;a href=&#34;https://en.wikipedia.org/wiki/Standard_streams&#34; target=&#34;_blank&#34;&gt;stdout&lt;/a&gt; because it then becomes the responsibility of the operating system/environment to determine where and how those logs are stored.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To quote &lt;a href=&#34;https://12factor.net/logs&#34; target=&#34;_blank&#34;&gt;12factor&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A (service) never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage log files. Instead, each running process writes its event stream, unbuffered, to stdout.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Applications should be conscious of the volume and &lt;a href=&#34;#3&#34;&gt;quality&lt;/a&gt; of the logs they emit. Logging isn&amp;rsquo;t free, and high volume logs aren&amp;rsquo;t necessarily more useful than fewer, thoughtful, log messages. Include important context with your log messages to be able to better understand the state of the system at that time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may discover that some log information is better off not logged but recorded as time series metrics so they can be provided and analysed by tools such as &lt;a href=&#34;https://www.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt;. The benefit of doing this is that you can more easily measure those metrics (and gain more insights) &lt;em&gt;over time&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can also, depending on the tools you use to analyse your log data (e.g. external log analysis system, such as &lt;a href=&#34;https://papertrailapp.com/&#34; target=&#34;_blank&#34;&gt;Papertrail&lt;/a&gt;), be better to log data in a more structured format in order to provide better contextual information and to make filtering logs easier. For more information on structured logging, I recommend &lt;a href=&#34;https://kartar.net/2015/12/structured-logging/&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt; inspired from &amp;ldquo;The Art of Monitoring&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;levels&#34;&gt;Levels&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When recording log data, there are various &amp;lsquo;levels&amp;rsquo; you can utilise that indicate different &lt;a href=&#34;https://en.wikipedia.org/wiki/Syslog#Severity_level&#34; target=&#34;_blank&#34;&gt;severities&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some common log levels along with a short description that describes when you would/should expect to use that particular level&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I saw these descriptions in a tweet a long time ago, and saved them off, and then months later when I&amp;rsquo;ve come to write this post I have since lost the link to the original tweet. If someone knows what it is, could you ping me on twitter and I&amp;rsquo;ll get the author credited appropriately.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;fatal&#34;&gt;Fatal&lt;/h3&gt;&#xA;&#xA;&lt;p class=&#34;ll-fatal&#34;&gt;Wake me up at 4am on a Sunday.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;error&#34;&gt;Error&lt;/h3&gt;&#xA;&#xA;&lt;p class=&#34;ll-error&#34;&gt;Apologize to the user and raise a ticket.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;warn&#34;&gt;Warn&lt;/h3&gt;&#xA;&#xA;&lt;p class=&#34;ll-warn&#34;&gt;Make a note in case it happens again.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;info&#34;&gt;Info&lt;/h3&gt;&#xA;&#xA;&lt;p class=&#34;ll-info&#34;&gt;Everything&#39;s fine, just checking in.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;debug&#34;&gt;Debug&lt;/h3&gt;&#xA;&#xA;&lt;p class=&#34;ll-debug&#34;&gt;Fill my hard-drive with stack traces.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quality&#34;&gt;Quality&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many &amp;ldquo;logging best practice&amp;rdquo; articles, below is a short bullet list pulled from &lt;a href=&#34;http://dev.splunk.com/view/logging/SP-CAAAFCK&#34; target=&#34;_blank&#34;&gt;Splunk&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I recommend reading through &lt;a href=&#34;http://dev.splunk.com/view/logging/SP-CAAAFCK&#34; target=&#34;_blank&#34;&gt;their article&lt;/a&gt; for the full details.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use clear key-value pairs&lt;/li&gt;&#xA;&lt;li&gt;Create events that humans can read&lt;/li&gt;&#xA;&lt;li&gt;Use timestamps for every event&lt;/li&gt;&#xA;&lt;li&gt;Use unique identifiers&lt;/li&gt;&#xA;&lt;li&gt;Log in text format&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. log an image’s attributes, but not the binary data itself&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Use developer-friendly formats&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. json&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Log more than just debugging events&lt;/li&gt;&#xA;&lt;li&gt;Use categories/levels&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;e.g. info, warn, error, debug&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Identify the source&lt;/li&gt;&#xA;&lt;li&gt;Keep multi-line events to a minimum&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/logging-101/</guid>
      <link>https://www.integralist.co.uk/posts/logging-101/</link>
      <pubDate>Sun, 12 Nov 2017 00:00:00 +0000</pubDate>
      <title>Logging 101</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;update&#34;&gt;UPDATE&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of October 2020 I joined the Fastly team to help improve Developer Relations&#xA;🎉&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means one of my many responsibilities will be to make this blog post&#xA;redundant by ensuring the &lt;a href=&#34;https://developer.fastly.com/&#34; target=&#34;_blank&#34;&gt;developer.fastly.com&lt;/a&gt;&#xA;content is as relevant and valuable as possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But until that time, remember that this post was written (and updated), from the&#xA;perspective of a long time customer, over many years and so the tone and&#xA;personality of this blog post doesn&amp;rsquo;t represent the opinions of Fastly in any&#xA;way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have any questions, then feel free to reach out to me.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;In this post I&amp;rsquo;m going to be explaining how the &lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&#xA;CDN&lt;/a&gt; works, with regards to their &amp;lsquo;programmatic edge&amp;rsquo;&#xA;feature (i.e. the ability to execute code on cache servers nearest to your&#xA;users).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We will be digging into quite a few different areas of their implementation,&#xA;such as their clustering solution, shielding, and various gotchas and caveats to&#xA;their service offering.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Be warned: this post is a monster!&lt;br&gt;It&amp;rsquo;ll take a long time to digest this&#xA;information&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/asleep.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/asleep.webp&#34; alt=&#34;asleep&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Fastly utilizes &amp;lsquo;free&amp;rsquo; software (Varnish) and extends it to fit their purposes,&#xA;but this extending of existing software can make things confusing when it comes&#xA;to understanding what underlying features work and how they work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In short: &lt;a href=&#34;https://varnish-cache.org/&#34; target=&#34;_blank&#34;&gt;Varnish&lt;/a&gt; is an HTTP accelerator.\ More&#xA;concretely it is a web application that acts like a &lt;a href=&#34;https://en.wikipedia.org/wiki/Reverse_proxy&#34; target=&#34;_blank&#34;&gt;HTTP&#xA;reverse-proxy&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You place Varnish in front of your application servers (those that are serving&#xA;HTTP content) and it will cache that content for you. If you want more&#xA;information on what Varnish cache can do for you, then I recommend reading&#xA;through their &lt;a href=&#34;https://varnish-cache.org/intro/index.html&#34; target=&#34;_blank&#34;&gt;introduction article&lt;/a&gt;&#xA;(and watching the video linked there as well).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.fastly.com/&#34; target=&#34;_blank&#34;&gt;Fastly&lt;/a&gt; is many things, but for most people they are a&#xA;CDN provider who utilise a highly customised version of Varnish. This post is&#xA;about Varnish and explaining a couple of specific features (such as hit-for-pass&#xA;and serving stale) and how they work in relation to Fastly&amp;rsquo;s implementation of&#xA;Varnish.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One stumbling block for Varnish is the fact that it only accelerates HTTP, not&#xA;HTTPS. In order to handle HTTPS you would need a TLS/SSL termination process&#xA;sitting in front of Varnish to convert HTTPS to HTTP. Alternatively you could&#xA;use a termination process (such as nginx) &lt;em&gt;behind&lt;/em&gt; Varnish to fetch the content&#xA;from your origins over HTTPS and to return it as HTTP for Varnish to then&#xA;process and cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Simple, right?&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/confusing.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/confusing.webp&#34; alt=&#34;confusing&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Fastly helps both with the HTTPS problem, and also with scaling Varnish&#xA;in general.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason for this post is because when dealing with Varnish and VCL it gets&#xA;very confusing having to jump between official documentation for VCL and&#xA;Fastly&amp;rsquo;s specific implementation of it. Even more so because the version of&#xA;Varnish Fastly are using is now quite old and yet they&amp;rsquo;ve also implemented some&#xA;features from more recent Varnish versions. Meaning you end up getting in a&#xA;muddle about what should and should not be the expected behaviour (especially&#xA;around the general request flow cycle).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately this is not a &amp;ldquo;VCL 101&amp;rdquo;. If you need help understanding anything&#xA;mentioned in this post, then I recommend reading:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://book.varnish-software.com/4.0/&#34; target=&#34;_blank&#34;&gt;Varnish Book&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://info.varnish-software.com/blog&#34; target=&#34;_blank&#34;&gt;Varnish Blog&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.fastly.com/blog&#34; target=&#34;_blank&#34;&gt;Fastly Blog&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Fastly also has a couple of &lt;em&gt;excellent&lt;/em&gt; articles on utilising the &lt;code&gt;Vary&lt;/code&gt; HTTP&#xA;header, which is highly recommended reading.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Lastly, as of May 2020, Fastly has started rolling out an updated developer&#xA;portal which hopes to address some of the &amp;lsquo;documentation&amp;rsquo; issues I&amp;rsquo;ve noted in&#xA;this post.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Fastly reached out to me to review their updated developer portal (inc. the new&#xA;layout of their reference and API documentation) and requested my feedback. I&#xA;was happy to report that (other than a few minor comments) I found it to be a&#xA;good start and I&amp;rsquo;m very much looking forward to many future improvements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, let&amp;rsquo;s crack on&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;varnish-basics&#34;&gt;Varnish Basics&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Varnish is a &amp;lsquo;state machine&amp;rsquo; and it switches between these states via calls to a&#xA;&lt;code&gt;return&lt;/code&gt; function (where you tell the &lt;code&gt;return&lt;/code&gt; function which state to move to).&#xA;The various states are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;recv&lt;/code&gt;: request is received and can be inspected/modified.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hash&lt;/code&gt;: generate a hash key from host/path and lookup key in cache.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hit&lt;/code&gt;: hash key was found in the cache.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;miss&lt;/code&gt;: hash key was not found in the cache.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass&lt;/code&gt;: content should be fetched from origin, regardless of if it exists in cache or not, and response will not be cached.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pipe&lt;/code&gt;: content should be fetched from origin, and no other VCL will be executed.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fetch&lt;/code&gt;: content has been fetched, we can now inspect/modify it before delivering it to the user.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;deliver&lt;/code&gt;: content has been cached (or not, depending on what you &lt;code&gt;return&lt;/code&gt; in &lt;code&gt;vcl_fetch&lt;/code&gt;) and ready to be delivered to the user.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For each state there is a corresponding subroutine that is executed. It has the&#xA;form &lt;code&gt;vcl_&amp;lt;state&amp;gt;&lt;/code&gt;, and so there is a &lt;code&gt;vcl_recv&lt;/code&gt;, &lt;code&gt;vcl_hash&lt;/code&gt;, &lt;code&gt;vcl_hit&lt;/code&gt; etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As an example, in &lt;code&gt;vcl_recv&lt;/code&gt; to change state to &amp;ldquo;pass&amp;rdquo; you would execute&#xA;&lt;code&gt;return(pass)&lt;/code&gt;. If you were in &lt;code&gt;vcl_fetch&lt;/code&gt; and wanted to avoid caching the&#xA;content (i.e. move to &lt;code&gt;vcl_pass&lt;/code&gt; before moving to &lt;code&gt;vcl_deliver&lt;/code&gt;), then you would&#xA;execute &lt;code&gt;return(pass)&lt;/code&gt; otherwise executing &lt;code&gt;return(deliver)&lt;/code&gt; from &lt;code&gt;vcl_fetch&lt;/code&gt;&#xA;would cache the origin response and move you to &lt;code&gt;vcl_deliver&lt;/code&gt; directly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For a state such as &lt;code&gt;vcl_miss&lt;/code&gt;, when that state function finishes executing it&#xA;will automatically trigger a request to the origin/backend service to acquire&#xA;the requested content. Once the content is requested, &lt;em&gt;then&lt;/em&gt; we end up at&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; where we can then inspect the response from the origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why at the end of &lt;code&gt;vcl_miss&lt;/code&gt; we change state by calling &lt;code&gt;return(fetch)&lt;/code&gt;.&#xA;It looks like we&amp;rsquo;re telling Varnish to &amp;lsquo;fetch&amp;rsquo; data but really we&amp;rsquo;re saying move&#xA;to the next logical state which is actually &lt;code&gt;vcl_fetch&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, as Varnish is a state machine, we have the ability to &amp;lsquo;restart&amp;rsquo; a&#xA;request (while also keeping any modifications you might have made to the request&#xA;intact). To do that you would call &lt;code&gt;return(restart)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/varnish.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/varnish.webp&#34; alt=&#34;varnish&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;^^ Varnish in action&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;states-vs-actions&#34;&gt;States vs Actions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;According to Fastly &lt;code&gt;vcl_hash&lt;/code&gt; is the only exception to the rule of&#xA;&lt;code&gt;return(&amp;lt;state&amp;gt;)&lt;/code&gt; because the value you provide to the &lt;code&gt;return&lt;/code&gt; function is not&#xA;a &lt;em&gt;state&lt;/em&gt; per se. The state function is called &lt;code&gt;vcl_hash&lt;/code&gt; but you don&amp;rsquo;t execute&#xA;&lt;code&gt;return(hash)&lt;/code&gt;. Instead you execute &lt;code&gt;return(lookup)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Fastly suggests this is to help distinguish that we&amp;rsquo;re performing an action and&#xA;not a state change (i.e. we&amp;rsquo;re going to &lt;em&gt;lookup&lt;/em&gt; the requested resource within&#xA;the cache).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although &lt;code&gt;vcl_miss&lt;/code&gt;&amp;rsquo;s &lt;code&gt;return(fetch)&lt;/code&gt; is a bit ambiguous considering we &lt;em&gt;could&lt;/em&gt;&#xA;maybe argue it&amp;rsquo;s also performing an &amp;lsquo;action&amp;rsquo; rather than a state change. Let&amp;rsquo;s&#xA;also not forget operations such as &lt;code&gt;return(restart)&lt;/code&gt; which looks to be&#xA;triggering an &amp;lsquo;action&amp;rsquo; rather than a state change (in that example you might&#xA;otherwise expect to execute something like &lt;code&gt;return(recv)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;varnish-default-vcl&#34;&gt;Varnish Default VCL&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When using the free version of Varnish, you&amp;rsquo;ll typically implement your own&#xA;custom VCL logic (e.g. add code to &lt;code&gt;vcl_recv&lt;/code&gt; or any of the other common VCL&#xA;subroutines). But it&amp;rsquo;s important to be aware that if you don&amp;rsquo;t &lt;code&gt;return&lt;/code&gt; an&#xA;action (e.g. &lt;code&gt;return(pass)&lt;/code&gt;, or trigger any of the other available Varnish&#xA;&amp;lsquo;states&amp;rsquo;), then Varnish will continue to execute its own built-in VCL logic&#xA;which sits beneath your custom VCL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can view the &amp;lsquo;default&amp;rsquo; (or &amp;lsquo;builtin&amp;rsquo;) logic for each version of Varnish via&#xA;GitHub:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/varnishcache/varnish-cache/blob/2.1/bin/varnishd/default.vcl&#34; target=&#34;_blank&#34;&gt;Varnish v2.1&lt;/a&gt; (the version used by Fastly)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/varnishcache/varnish-cache/blob/3.0/bin/varnishd/default.vcl&#34; target=&#34;_blank&#34;&gt;Varnish v3.0&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/varnishcache/varnish-cache/blob/4.0/bin/varnishd/builtin.vcl&#34; target=&#34;_blank&#34;&gt;Varnish v4.0&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/varnishcache/varnish-cache/blob/5.0/bin/varnishd/builtin.vcl&#34; target=&#34;_blank&#34;&gt;Varnish v5.0&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;after v3 Varnish renamed the file from &lt;code&gt;default.vcl&lt;/code&gt; to &lt;code&gt;builtin.vcl&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But things are slightly different with Fastly&amp;rsquo;s Varnish implementation (which is&#xA;based off Varnish version 2.1.5).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;no &lt;code&gt;return(pipe)&lt;/code&gt; in &lt;code&gt;vcl_recv&lt;/code&gt;, they do &lt;code&gt;pass&lt;/code&gt; there&lt;/li&gt;&#xA;&lt;li&gt;some modifications to the &lt;code&gt;synthetic&lt;/code&gt; in &lt;code&gt;vcl_error&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&amp;hellip;and God knows what else.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-default-vcl&#34;&gt;Fastly Default VCL&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;On top of the built-in VCL the free version of Varnish uses, Fastly also&#xA;includes its own &amp;lsquo;default&amp;rsquo; VCL logic alongside your custom VCL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When creating a new Fastly &amp;lsquo;service&amp;rsquo;, this default VCL is added automatically to&#xA;your new service. You are then free to remove it completely and replace it with&#xA;your own custom VCL if you like.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See the link below for what this default VCL looks like, but in there you&amp;rsquo;ll&#xA;notice code comments such as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#--FASTLY RECV BEGIN&#xA;&#xA;...code here...&#xA;&#xA;#--FASTLY RECV END&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;those specific portions of the default code define &lt;em&gt;critical&lt;/em&gt; behaviour&#xA;that needs to be defined whenever you want to write &lt;a href=&#34;#3.0&#34;&gt;your own custom&#xA;VCL&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Fastly has some guidelines around the use (or removal) of their default VCL&#xA;which you can learn more about&#xA;&lt;a href=&#34;https://docs.fastly.com/guides/vcl/mixing-and-matching-fastly-vcl-with-custom-vcl&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some useful links to see Fastly&amp;rsquo;s default VCL:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/2e4a78fe92ec70d2e2709ff7be660669&#34; target=&#34;_blank&#34;&gt;Fastly&amp;rsquo;s Default VCL (full service context)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/56cf991ae97551583d5a2f0d69f37788&#34; target=&#34;_blank&#34;&gt;Fastly&amp;rsquo;s Default VCL (each state split into separate files)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Fastly also has what they call a &amp;lsquo;master&amp;rsquo; VCL which runs outside of what&#xA;we (as customers) can see, and this VCL is used to help Fastly scale varnish&#xA;(e.g. handle things like their custom clustering solution).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/cant-see-me.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/cant-see-me.webp&#34; alt=&#34;cant see me&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;fastly&amp;rsquo;s master VCL be all like ^^&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-vcl&#34;&gt;Custom VCL&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When adding your own custom VCL code you&amp;rsquo;ll need to ensure that you add Fastly&amp;rsquo;s&#xA;critical default behaviours, otherwise things might not work as expected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way you add their defaults to your own custom VCL code is to add a specific&#xA;type of code comment, for example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_recv {&#xA;  #FASTLY recv&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;See &lt;a href=&#34;https://docs.fastly.com/vcl/custom-vcl/creating-custom-vcl/&#34; target=&#34;_blank&#34;&gt;their&#xA;documentation&lt;/a&gt; for&#xA;more details, but ultimately these code comments are &amp;lsquo;macros&amp;rsquo; that get expanded&#xA;into the actual default VCL code at compile time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can be useful to know what the default VCL code does (see &lt;a href=&#34;#3&#34;&gt;links in previous&#xA;section&lt;/a&gt;) because it might affect where you place these macros within your&#xA;own custom code (e.g. do you place it in the middle of your custom sub routines&#xA;or at the start or the end).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is important because, for example, the default behaviours Fastly defines&#xA;for &lt;code&gt;vcl_recv&lt;/code&gt; is to set a backend for your service. Your custom VCL can of&#xA;course override that backend, but where you define your custom code that does&#xA;that overriding might not function correctly if placed in the wrong place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Here is an example of why it&amp;rsquo;s important to know what is happening inside of&#xA;these macros&lt;/strong&gt;: we had a conditional comment that looked something like the&#xA;following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.restarts == 0) {&#xA;  ...set backend...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;later on in our VCL we would trigger a request restart (e.g.&#xA;&lt;code&gt;return(restart)&lt;/code&gt;), but now &lt;code&gt;req.restarts&lt;/code&gt; would be equal to &lt;code&gt;1&lt;/code&gt; and not zero&#xA;and so when the request restarted we wouldn&amp;rsquo;t set the backend.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, this of course is a bug in our code and has nothing to do with the default&#xA;Fastly VCL (yet). But what&amp;rsquo;s important to now be aware of is that our requests&#xA;didn&amp;rsquo;t just &amp;lsquo;fail&amp;rsquo; but were sent to a different origin altogether (which was&#xA;extremely confusing to debug at the time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Turns out what was happening was that the default Fastly VCL was selecting a&#xA;&lt;em&gt;default&lt;/em&gt; backend for us, and this selection was based on the &lt;em&gt;age&lt;/em&gt; of the&#xA;backend!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To quote Fastly directly&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;We choose the first backend that was created that doesn&amp;rsquo;t have a conditional&#xA;on it. If all of your backends have conditionals on them, I believe we then&#xA;just use the first backend that was created. If a backend has a conditional on&#xA;it, we assume it isn&amp;rsquo;t a default. That backend is only set under the&#xA;conditions defined, so then we look for the oldest backend defined that&#xA;doesn’t have a conditional to make it the default.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;be-careful&#34;&gt;Be Careful!&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We experienced a problem that broke our production site and it was related to&#xA;implementing our own &lt;code&gt;vcl_hash&lt;/code&gt; subroutine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem wasn&amp;rsquo;t as obvious as you might think. We didn&amp;rsquo;t implement &lt;code&gt;vcl_hash&lt;/code&gt;&#xA;to change the hashing algorithm, but instead we wanted to add some debug log&#xA;calls into it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We looked at the VCL that Fastly generated before we added our own &lt;code&gt;vcl_hash&lt;/code&gt;&#xA;subroutine and that VCL looked like the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_hash {&#xA;#--FASTLY HASH BEGIN&#xA;  #if unspecified fall back to normal&#xA;  {&#xA;    set req.hash += req.url;&#xA;    set req.hash += req.http.host;&#xA;    set req.hash += &amp;quot;#####GENERATION#####&amp;quot;;&#xA;    return (hash);&#xA;  }&#xA;#--FASTLY HASH END&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We thought &amp;ldquo;OK, that&amp;rsquo;s what Fastly is generating, so we&amp;rsquo;ll just let them&#xA;continue generating that code, nothing special we need to do&amp;rdquo; &amp;hellip;wrong!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we added the following code to our own VCL&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_hash {&#xA;  #FASTLY hash&#xA;&#xA;  call debug_info;&#xA;&#xA;  return(hash)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The expectation was that the &lt;code&gt;#FASTLY hash&lt;/code&gt; macro would still include all the&#xA;code from inbetween &lt;code&gt;#--FASTLY HASH BEGIN&lt;/code&gt; and &lt;code&gt;#--FASTLY HASH END&lt;/code&gt; (see the&#xA;earlier code snippet).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What actually ended up happening was that the Fastly macro dynamically changed&#xA;itself to not include critical behaviours&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice the &lt;code&gt;set req.hash += req.url;&lt;/code&gt; and &lt;code&gt;set req.hash += req.http.host;&lt;/code&gt; that&#xA;they originally were generating? Yup. They were no longer included. This caused&#xA;the system caching to blow up.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The code that was being generated now looked like the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#--FASTLY HASH BEGIN&#xA;# support purge all&#xA;set req.hash += req.vcl.generation;&#xA;#--FASTLY HASH END&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So to fix the problem we had to put those missing settings manually back into&#xA;our own &lt;code&gt;vcl_hash&lt;/code&gt; subroutine&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_hash {&#xA;  #FASTLY hash&#xA;&#xA;  set req.hash += req.url;&#xA;  set req.hash += req.http.host;&#xA;&#xA;  call debug_info;&#xA;&#xA;  return(hash);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Interestingly Fastly&amp;rsquo;s default VCL &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; require us to also set &lt;code&gt;set req.hash += &amp;quot;#####GENERATION#####&amp;quot;;&lt;/code&gt;, so they happily keep that part within&#xA;their generated code 🤦&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/ok-fine.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/ok-fine.webp&#34; alt=&#34;ok fine&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;example-boilerplate&#34;&gt;Example Boilerplate&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Before we move on, while we&amp;rsquo;re discussing custom VCL, I&amp;rsquo;d like to share with you&#xA;some VCL boilerplate I typically start out all new projects with (which I then&#xA;modify to suit the project&amp;rsquo;s requirements, but ultimately this VCL consists of&#xA;all the standard stuff you&amp;rsquo;d typically would need):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#&#xA;# detailed blog post on fastly&#39;s implementation details:&#xA;# https://www.integralist.co.uk/posts/fastly-varnish/&#xA;#&#xA;# fastly custom vcl boilerplate:&#xA;# https://docs.fastly.com/vcl/custom-vcl/creating-custom-vcl/#fastlys-vcl-boilerplate&#xA;#&#xA;# states defined in this file:&#xA;# vcl_recv&#xA;# vcl_error&#xA;# vcl_hash&#xA;# vcl_pass&#xA;# vcl_miss&#xA;# vcl_hit&#xA;# vcl_fetch&#xA;# vcl_deliver&#xA;#&#xA;&#xA;table deny_list {&#xA;  &amp;quot;/bad-thing-1&amp;quot;: &amp;quot;true&amp;quot;,&#xA;  &amp;quot;/bad-thing-2&amp;quot;: &amp;quot;true&amp;quot;,&#xA;}&#xA;&#xA;sub set_backend {&#xA;  set req.backend = F_httpbin;&#xA;&#xA;  if (req.http.Host == &amp;quot;example-stage.acme.com/&amp;quot;) {&#xA;   set req.backend = F_httpbin_stage;&#xA;  }&#xA;}&#xA;&#xA;sub vcl_recv {&#xA;  #FASTLY recv&#xA;&#xA;  call set_backend;&#xA;&#xA;  # configure purges to require api authentication:&#xA;  # https://docs.fastly.com/en/guides/authenticating-api-purge-requests&#xA;  #&#xA;  if (req.method == &amp;quot;FASTLYPURGE&amp;quot;) {&#xA;      set req.http.Fastly-Purge-Requires-Auth = &amp;quot;1&amp;quot;;&#xA;  }&#xA;&#xA;  # force HTTP to HTTPS&#xA;  #&#xA;  # related: req.http.Fastly-SSL&#xA;  # https://docs.fastly.com/en/guides/tls-termination&#xA;  #&#xA;  if (req.protocol != &amp;quot;https&amp;quot;) {&#xA;    error 601 &amp;quot;Force SSL&amp;quot;;&#xA;  }&#xA;&#xA;  # fastly &#39;tables&#39; are different to &#39;edge dictionaries&#39;:&#xA;  # https://docs.fastly.com/en/guides/about-edge-dictionaries&#xA;  #&#xA;  if (table.lookup(deny_list, req.url.path)) {&#xA;    error 600 &amp;quot;Not found&amp;quot;;&#xA;  }&#xA;&#xA;  # don&#39;t bother doing a cache lookup for a request type that isn&#39;t cacheable&#xA;  if (req.method !~ &amp;quot;(GET|HEAD|FASTLYPURGE)&amp;quot;) {&#xA;    return(pass);&#xA;  }&#xA;&#xA;  if (req.restarts == 0) {&#xA;    # nagios/monitoring cache bypass&#xA;    #&#xA;    if (req.url ~ &amp;quot;123&amp;quot;) {&#xA;      set req.http.X-Monitoring = &amp;quot;true&amp;quot;;&#xA;      return(pass);&#xA;    }&#xA;  }&#xA;&#xA;  return(lookup);&#xA;}&#xA;&#xA;sub vcl_error {&#xA;  #FASTLY error&#xA;&#xA;  # fastly synthetic error responses:&#xA;  # https://docs.fastly.com/en/guides/creating-error-pages-with-custom-responses&#xA;  #&#xA;  if (obj.status == 600) {&#xA;    set obj.status = 404;&#xA;&#xA;    synthetic {&amp;quot;&#xA;      &amp;lt;!doctype html&amp;gt;&#xA;      &amp;lt;html&amp;gt;&#xA;        &amp;lt;head&amp;gt;&#xA;          &amp;lt;meta charset=&amp;quot;utf-8&amp;quot;&amp;gt;&#xA;          &amp;lt;title&amp;gt;Error&amp;lt;/title&amp;gt;&#xA;        &amp;lt;/head&amp;gt;&#xA;        &amp;lt;body&amp;gt;&#xA;          &amp;lt;h1&amp;gt;404 Not Found (varnish)&amp;lt;/h1&amp;gt;&#xA;        &amp;lt;/body&amp;gt;&#xA;      &amp;lt;/html&amp;gt;&#xA;      &amp;quot;};&#xA;&#xA;    return(deliver);&#xA;  }&#xA;&#xA;  # fastly HTTP to HTTPS 301 redirect:&#xA;  # https://docs.fastly.com/en/guides/generating-http-redirects-at-the-edge&#xA;  #&#xA;  # example:&#xA;  # curl -sD - http://example.acme.com/&#xA;  # curl -H Fastly-Debug:1 -sLD - -o /dev/null http://example.acme.com/?cachebust=$(uuidgen)&#xA;  #&#xA;  if (obj.status == 601 &amp;amp;&amp;amp; obj.response == &amp;quot;Force SSL&amp;quot;) {&#xA;    set obj.status = 301;&#xA;    set obj.response = &amp;quot;Moved Permanently&amp;quot;;&#xA;    set obj.http.Location = &amp;quot;https://&amp;quot; req.http.host req.url;&#xA;    synthetic {&amp;quot;&amp;quot;};&#xA;    return (deliver);&#xA;  }&#xA;}&#xA;&#xA;sub vcl_hash {&#xA;  #FASTLY hash&#xA;&#xA;  set req.hash += req.url;&#xA;  set req.hash += req.http.host;&#xA;&#xA;  # call debug_info_hash;&#xA;&#xA;  return(hash);&#xA;}&#xA;&#xA;sub vcl_pass {&#xA;  #FASTLY pass&#xA;}&#xA;&#xA;sub vcl_miss {&#xA;  #FASTLY miss&#xA;&#xA;  return(fetch);&#xA;}&#xA;&#xA;sub vcl_hit {&#xA;  #FASTLY hit&#xA;}&#xA;&#xA;sub vcl_fetch {&#xA;  #FASTLY fetch&#xA;&#xA;  # fastly caching directive:&#xA;  # https://docs.fastly.com/en/guides/cache-control-tutorial&#xA;  #&#xA;  # example:&#xA;  # define stale behaviour if none provided by origin&#xA;  #&#xA;  if (beresp.http.Surrogate-Control !~ &amp;quot;(stale-while-revalidate|stale-if-error)&amp;quot;) {&#xA;    set beresp.stale_if_error = 31536000s; // 1 year&#xA;    set beresp.stale_while_revalidate = 60s; // 1 minute&#xA;  }&#xA;&#xA;  # fastly stale-if-error:&#xA;  # https://docs.fastly.com/en/guides/serving-stale-content&#xA;  #&#xA;  if (beresp.status &amp;gt;= 500 &amp;amp;&amp;amp; beresp.status &amp;lt; 600) {&#xA;    if (stale.exists) {&#xA;      return(deliver_stale);&#xA;    }&#xA;  }&#xA;&#xA;  # hit-for-pass:&#xA;  # https://www.integralist.co.uk/posts/fastly-varnish/#hit-for-pass&#xA;  #&#xA;  if (beresp.http.Cache-Control ~ &amp;quot;private&amp;quot;) {&#xA;    return(pass);&#xA;  }&#xA;&#xA;  return(deliver);&#xA;}&#xA;&#xA;sub vcl_deliver {&#xA;  #FASTLY deliver&#xA;&#xA;  # fastly internal state information:&#xA;  # https://docs.fastly.com/en/guides/useful-variables-to-log&#xA;  #&#xA;  set resp.http.Fastly-State = fastly_info.state;&#xA;&#xA;  if (req.http.X-Monitoring == &amp;quot;true&amp;quot;) {&#xA;    set resp.http.X-Monitoring = req.http.X-Monitoring;&#xA;  }&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;UPDATE 2020.02.25: Fastly have published a blog post that details what they&#xA;consider to be VCL anti-patterns and offer solutions/alternative patterns:&#xA;&lt;a href=&#34;https://www.fastly.com/blog/maintainable-vcl&#34; target=&#34;_blank&#34;&gt;https://www.fastly.com/blog/maintainable-vcl&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-ttls&#34;&gt;Fastly TTLs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When Fastly caches your content, it of course only caches it for a set period of&#xA;time (known as the content&amp;rsquo;s &amp;ldquo;Time To Live&amp;rdquo;, or TTL). Fastly &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/controlling-caching&#34; target=&#34;_blank&#34;&gt;has some&#xA;rules&lt;/a&gt;&#xA;about how it determines a TTL for your content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Their &amp;lsquo;master&amp;rsquo; VCL sets a TTL of 120s (&lt;a href=&#34;https://github.com/varnishcache/varnish-cache/blob/5.0/bin/varnishd/builtin.vcl#L158-L172&#34; target=&#34;_blank&#34;&gt;this comes from&#xA;Varnish&lt;/a&gt;&#xA;rather than Fastly) when no other VCL TTL has been defined and if no cache&#xA;headers were sent by the origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Fastly does a similar thing with its own default VCL which it uses when you&#xA;create a new service. It looks like the following and increases the default to&#xA;3600s (1hr):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (beresp.http.Expires || &#xA;    beresp.http.Surrogate-Control ~ &amp;quot;max-age&amp;quot; || &#xA;    beresp.http.Cache-Control ~&amp;quot;(s-maxage|max-age)&amp;quot;) {&#xA;  # keep the ttl here&#xA;} else {&#xA;  # apply the default ttl&#xA;  set beresp.ttl = 3600s;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;3600 isn&amp;rsquo;t long enough to persist your cached content to disk, it will&#xA;exist in-memory only. See their documentation on &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/serving-stale-content#why-serving-stale-content-may-not-work-as-expected&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;Why serving stale content&#xA;may not work as&#xA;expected&amp;rdquo;&lt;/a&gt;&#xA;for more information.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You can override this VCL with your own custom VCL, but it&amp;rsquo;s also worth being&#xA;aware of the priority ordering Fastly gives when presented with multiple ways to&#xA;determine your content&amp;rsquo;s cache TTL&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;beresp.ttl = 10s&lt;/code&gt;: caches for 10s&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control: max-age=300&lt;/code&gt; caches for 5 minutes&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control: max-age=10&lt;/code&gt; caches for 10s&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires: Fri, 28 June 2008 15:00:00 GMT&lt;/code&gt; caches until this date has expired&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;As we can see from the above list, setting a TTL via VCL takes ultimate priority&#xA;even if caching headers are provided by the origin server.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dns-ttl-caching&#34;&gt;DNS TTL Caching&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two fundamental pieces of information I&amp;rsquo;m about to describe&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;p&gt;Fastly only uses the first IP returned from a DNS lookup, and will cache it&#xA;until the DNS&amp;rsquo; TTL expires. A failed DNS lookup for a service without a&#xA;Fastly &amp;lsquo;health check&amp;rsquo; (see&#xA;&lt;a href=&#34;https://docs.fastly.com/en/guides/working-with-health-checks&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;) would lead&#xA;to 600 seconds (10 minutes!) of stale IP use before attempting to requery the&#xA;DNS.\ &lt;strong&gt;An example of why this is bad&lt;/strong&gt;: we had a 60s DNS TTL to align with that&#xA;of AWS load balancers, but we discovered we were getting Fastly errors for ten&#xA;minutes instead of just 1 minute.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Fastly does offer a &amp;lsquo;High Availability&amp;rsquo; feature (on request) which allows for&#xA;traffic distribution across &lt;em&gt;multiple&lt;/em&gt; IPs returned from a DNS lookup, rather&#xA;than just using one until the next DNS lookup.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;caching-priority-list&#34;&gt;Caching Priority List&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Fastly &lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial&#34; target=&#34;_blank&#34;&gt;has some&#xA;rules&lt;/a&gt; about&#xA;the various caching response headers it respects and in what order this&#xA;behaviour is applied. The following is a summary of these rules:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control&lt;/code&gt; determines proxy caching behaviour (takes priority over &lt;code&gt;Cache-Control&lt;/code&gt;) †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines client caching behaviour.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines both client/proxy caching behaviour if no &lt;code&gt;Surrogate-Control&lt;/code&gt; †.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt; determines both client/proxy caching behaviour if it includes both &lt;code&gt;max-age&lt;/code&gt; and &lt;code&gt;s-maxage&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt; determines both client/proxy caching behaviour if no &lt;code&gt;Cache-Control&lt;/code&gt; or &lt;code&gt;Surrogate-Control&lt;/code&gt; headers.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt; ignored if &lt;code&gt;Cache-Control&lt;/code&gt; is also set (recommended to avoid &lt;code&gt;Expires&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Pragma&lt;/code&gt; is a legacy cache header only recommended if you need to support older HTTP/1.0 protocol.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† &lt;em&gt;except&lt;/em&gt; when &lt;code&gt;Cache-Control&lt;/code&gt; contains &lt;code&gt;private&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Next in line is &lt;code&gt;Surrogate-Control&lt;/code&gt; (see &lt;a href=&#34;/posts/http-caching-guide/&#34;&gt;my post on HTTP&#xA;caching&lt;/a&gt; for more information on this cache header),&#xA;which takes priority over &lt;code&gt;Cache-Control&lt;/code&gt;. The &lt;code&gt;Cache-Control&lt;/code&gt; header itself&#xA;takes priority over &lt;code&gt;Expires&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you ever want to debug Fastly and your custom VCL then it&amp;rsquo;s&#xA;recommended you create a &amp;lsquo;reduced test case&amp;rsquo; using their &lt;a href=&#34;https://fiddle.fastlydemo.net/&#34; target=&#34;_blank&#34;&gt;Fastly&#xA;Fiddle&lt;/a&gt; tool. Be aware this tool shares code&#xA;publicly so don&amp;rsquo;t put secret codes or logic into it! Don&amp;rsquo;t forget to add&#xA;&lt;code&gt;return&lt;/code&gt; statements to the functions in the Fiddle UI, otherwise the default&#xA;Fastly boilerplate VCL will be executed and that can cause confusion if your&#xA;service typically doesn&amp;rsquo;t use it! e.g. httpbin origin was sending back a 500&#xA;and &lt;code&gt;vcl_fetch&lt;/code&gt; was triggering a restart and I didn&amp;rsquo;t know why. I discovered I&#xA;had to add &lt;code&gt;return(deliver)&lt;/code&gt; in &lt;code&gt;vcl_fetch&lt;/code&gt; to prevent Fastly boilerplate from&#xA;executing!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-default-cached-status-codes&#34;&gt;Fastly Default Cached Status Codes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The CDN (Fastly) &lt;a href=&#34;https://docs.fastly.com/en/guides/http-status-codes-cached-by-default&#34; target=&#34;_blank&#34;&gt;doesn&amp;rsquo;t cache all&#xA;responses&lt;/a&gt;.&#xA;It will not cache any responses with a status code in the &lt;code&gt;5xx&lt;/code&gt; range, and it&#xA;will only cache a tiny subset of responses with a status code in the &lt;code&gt;4xx&lt;/code&gt; and&#xA;&lt;code&gt;3xx&lt;/code&gt; range.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The status codes it will cache by default are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;200 OK&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;203 Non-Authoritative Information&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;300 Multiple Choices&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;301 Moved Permanently&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;302 Moved Temporarily&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;404 Not Found&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;410 Gone&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in VCL you can allow &lt;em&gt;any&lt;/em&gt; response status code to be cached by&#xA;executing &lt;code&gt;set beresp.cacheable = true;&lt;/code&gt; within &lt;code&gt;vcl_fetch&lt;/code&gt; (you can also&#xA;change the status code if you like to &lt;em&gt;look&lt;/em&gt; like it was a different code with&#xA;&lt;code&gt;set beresp.status = &amp;lt;new_status_code&amp;gt;;&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;fastly-request-flow-diagram&#34;&gt;Fastly Request Flow Diagram&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are various request flow diagrams for Varnish&#xA;(&lt;a href=&#34;http://book.varnish-software.com/4.0/_images/simplified_fsm.svg&#34; target=&#34;_blank&#34;&gt;example&lt;/a&gt;) and&#xA;generally they separate the request flow into two sections: request and backend.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So handling the request, looking up the hash key in the cache, getting a hit or&#xA;miss, or opening a pipe to the origin are all considered part of the &amp;ldquo;request&amp;rdquo;&#xA;section. Whereas fetching of the content is considered part of the &amp;ldquo;backend&amp;rdquo;&#xA;section.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The purpose of the distinction is because Varnish likes to handle backend&#xA;fetches &lt;em&gt;asynchronously&lt;/em&gt;. This means Varnish can serve stale data while a new&#xA;version of the cached object is being fetched. This means less request queuing&#xA;when the backend is slow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But the issue with these diagrams is that they&amp;rsquo;re not all the same. Changes&#xA;between Varnish versions and also the difference in Fastly&amp;rsquo;s implementation make&#xA;identifying the right request flow tricky.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a diagram of Fastly&amp;rsquo;s VCL request flow (including its WAF and&#xA;Clustering logic). This is a great reference for confirming how your VCL logic&#xA;is expected to behave.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/fastly-request-flow.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/fastly-request-flow.png&#34; alt=&#34;fastly request flow&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;fastly-debug&#34;&gt;Fastly-Debug&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Fastly will display extra information about a request/response flow within its&#xA;HTTP response headers if the request was issued with a &lt;code&gt;Fastly-Debug&lt;/code&gt; HTTP&#xA;request header (set with a value of &lt;code&gt;1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some of the extra headers you&amp;rsquo;ll find in the response are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Fastly-Debug-Digest&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Fastly-Debug-Path&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Fastly-Debug-TTL&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Control&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Surrogate-Key&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-Cache-Hits&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-Cache&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;X-Served-By&lt;/code&gt; (reports fetching node, see &lt;a href=&#34;#clustering&#34;&gt;Clustering&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;Surrogate-*&lt;/code&gt; response headers are typically set by an origin server&#xA;and are otherwise stripped by Fastly.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Some of the following information will make reference to &amp;lsquo;delivery&amp;rsquo; and&#xA;&amp;lsquo;fetching&amp;rsquo; nodes. It&amp;rsquo;s probably best you read ahead to the section on&#xA;&lt;a href=&#34;#clustering&#34;&gt;clustering&lt;/a&gt; to understand what these concepts mean in the scope of&#xA;Fastly&amp;rsquo;s system design. Once you understand them, come back here and the next&#xA;few sentences will make more sense.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The quick summary is this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;delivery node: the cache server your request is first routed to (and which&#xA;sends the response back to you).&lt;/li&gt;&#xA;&lt;li&gt;fetching node: the cache server that actually makes a request to your origin,&#xA;before returning the origin response back to the delivery node.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;When using &lt;code&gt;Fastly-Debug:1&lt;/code&gt; to inspect debug response headers, we might want to&#xA;look at &lt;code&gt;fastly-state&lt;/code&gt;, &lt;code&gt;fastly-debug-path&lt;/code&gt; and &lt;code&gt;fastly-debug-ttl&lt;/code&gt;. These would&#xA;have values such as&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt; fastly-state: HIT-STALE&#xA;&amp;lt; fastly-debug-path: (D cache-lhr6346-LHR 1563794040) (F cache-lhr6324-LHR 1563794019)&#xA;&amp;lt; fastly-debug-ttl: (H cache-lhr6346-LHR -10.999 31536000.000 20)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;fastly-debug-path&lt;/code&gt; suggests we delivered from the delivery node &lt;code&gt;lhr6346&lt;/code&gt;,&#xA;while we fetched from the fetching node &lt;code&gt;lhr6324&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;fastly-debug-ttl&lt;/code&gt; header suggests we got a HIT (&lt;code&gt;H&lt;/code&gt;) from the delivery node&#xA;&lt;code&gt;lhr6346&lt;/code&gt;, but this is a misleading header and one you need to be careful with.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it may take a few requests to see numbers populating the&#xA;&lt;code&gt;Fastly-Debug-TTL&lt;/code&gt;, as the request needs to either land on the fetching node,&#xA;or a delivery node where the content exists in temporary memory. If you see&#xA;&lt;code&gt;-&lt;/code&gt; it might be because you arrived at a delivery node that doesn&amp;rsquo;t have it&#xA;in-memory.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Why this header is misleading is actually quite a hard thing to explain, and&#xA;Fastly has discussed the reasoning for the confusion in at least a couple&#xA;different talks I&amp;rsquo;ve seen (one being:&#xA;&lt;a href=&#34;https://vimeo.com/showcase/6623864/video/376921467&#34; target=&#34;_blank&#34;&gt;https://vimeo.com/showcase/6623864/video/376921467&lt;/a&gt; which I highly recommend&#xA;btw).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence, the HIT state is recorded at the fetching node. When the response&#xA;makes its way back to the delivery node, it will then set the&#xA;&lt;code&gt;fastly-debug-ttl&lt;/code&gt;. But this doesn&amp;rsquo;t mean that the cache HIT &lt;em&gt;happened&lt;/em&gt; at the&#xA;delivery node, only that the header was &lt;em&gt;set&lt;/em&gt; there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this is a concern is that you don&amp;rsquo;t necessarily know if the request&#xA;did indeed go to the fetching node or whether the stale content actually came&#xA;from the delivery node&amp;rsquo;s in-memory cache. The only way to be sure is to check&#xA;the &lt;code&gt;fastly-state&lt;/code&gt; response header.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;fastly-state&lt;/code&gt; header is ultimately what I use to verify where something has&#xA;happened. If I see a &lt;code&gt;HIT&lt;/code&gt; (or &lt;code&gt;HIT-STALE&lt;/code&gt;), then I know I got a cache HIT from&#xA;the delivery node (e.g. myself or someone else has already requested the&#xA;resource via this delivery node).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a reported &lt;code&gt;HIT&lt;/code&gt; can in some cases be because the first cache server&#xA;your request was routed to &lt;em&gt;was&lt;/em&gt; the primary node (again, see&#xA;&lt;a href=&#34;#clustering&#34;&gt;clustering&lt;/a&gt; for details of what a &amp;lsquo;primary&amp;rsquo; node is in relation&#xA;to a &amp;lsquo;fetching&amp;rsquo; node).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If I see instead a &lt;code&gt;HIT-CLUSTER&lt;/code&gt; (or &lt;code&gt;HIT-STALE-CLUSTER&lt;/code&gt;) it means I&amp;rsquo;m the first&#xA;person to reach this delivery node and request this resource, and so there was&#xA;nothing cached and thus we went to the fetching node and got a cache HIT there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another confusing aspect to &lt;code&gt;fastly-debug-ttl&lt;/code&gt; is that with regards to&#xA;&lt;code&gt;stale-while-revalidate&lt;/code&gt; you could end up seeing a &lt;code&gt;-&lt;/code&gt; in the section where you&#xA;might otherwise expect to see the grace period of the object (i.e. how long can&#xA;it be served stale for while revalidating). This can occur when the origin&#xA;server hasn&amp;rsquo;t sent back either an &lt;code&gt;ETag&lt;/code&gt; header or &lt;code&gt;Last-Modified&lt;/code&gt; header.&#xA;Fastly still serves stale content if the &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL is still&#xA;valid but the output of the &lt;code&gt;fastly-debug-ttl&lt;/code&gt; can be confusing and/or&#xA;misleading.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Something else to note, while I write this August 2019 update is that the&#xA;&lt;code&gt;fastly-debug-ttl&lt;/code&gt; only every displays the &amp;lsquo;grace&amp;rsquo; value when it comes to&#xA;&lt;code&gt;stale-if-error&lt;/code&gt;, meaning if you&amp;rsquo;re trying to check if you&amp;rsquo;re serving&#xA;&lt;code&gt;stale-while-revalidate&lt;/code&gt; by looking at the grace period you might get confused&#xA;when you see the &lt;code&gt;stale-if-error&lt;/code&gt; grace period (or worse a &lt;code&gt;-&lt;/code&gt; value), this is&#xA;because the &lt;code&gt;fastly-debug-ttl&lt;/code&gt; header isn&amp;rsquo;t as granular as it should be.&#xA;Fastly have indicated that they intend on making updates to this header in the&#xA;future in order for the values to be much clearer.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Lastly, when dealing with shielding the &lt;code&gt;fastly-debug-ttl&lt;/code&gt; can be misleading in&#xA;another sense which is: imagine the fetching node got a MISS (so it fetched&#xA;content from origin and returned it to the delivery node). The delivery node&#xA;will cache the response from the fetching node (including the MISS reported by&#xA;&lt;code&gt;fastly-debug-ttl&lt;/code&gt;) and so even if another request reaches the name delivery&#xA;node, it will report a &lt;code&gt;MISS, HIT&lt;/code&gt; combination.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/you-lose.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/you-lose.webp&#34; alt=&#34;you lose&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;thanks Fastly, for this totally not confusing setup ^^&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;304-not-modified&#34;&gt;304 Not Modified&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Although not specifically mentioned in the above diagram it&amp;rsquo;s worth noting that&#xA;Fastly doesn&amp;rsquo;t execute &lt;code&gt;vcl_fetch&lt;/code&gt; when it receives a &lt;code&gt;304 Not Modified&lt;/code&gt; from&#xA;origin, but it will use any &lt;code&gt;Cache-Control&lt;/code&gt; or &lt;code&gt;Surrogate-Control&lt;/code&gt; values&#xA;defined on that response to determine how long the stale object should now be&#xA;kept in cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If no caching headers are sent with the &lt;code&gt;304 Not Modified&lt;/code&gt; response, then the&#xA;stale object&amp;rsquo;s TTL is &lt;em&gt;refreshed&lt;/em&gt;. This means its age is set back to zero and&#xA;the original &lt;code&gt;max-age&lt;/code&gt; TTL is enforced.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately this means if you were hoping to execute logic defined within&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; whenever a &lt;code&gt;304 Not Modified&lt;/code&gt; was returned (e.g. dynamically modify&#xA;the stale/cached object&amp;rsquo;s TTL), then that isn&amp;rsquo;t possible.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;update-2019-08-10&#34;&gt;UPDATE 2019.08.10&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Fastly reached out to me to let me know that this diagram is now incorrect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically, the request flow for a hit-for-pass (&lt;a href=&#34;#5&#34;&gt;see below&lt;/a&gt; for details)&#xA;&lt;em&gt;was&lt;/em&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;RECV, HASH, HIT, PASS, DELIVER&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where &lt;code&gt;vcl_hit&lt;/code&gt; would &lt;code&gt;return(pass)&lt;/code&gt; once it had identified the cached object as&#xA;being a hit-for-pass object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is now:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;RECV, HASH, PASS, DELIVER&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where after the object is returned from &lt;code&gt;vcl_hash&lt;/code&gt;&amp;rsquo;s lookup, it&amp;rsquo;s immediately&#xA;identified as being a HFP (hit-for-pass) and thus triggers &lt;code&gt;vcl_pass&lt;/code&gt; as the&#xA;next state, and finally &lt;code&gt;vcl_deliver&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What this ultimately means is there is some redundant code later on in this blog&#xA;post where I make reference to serving stale content. Specifically, I mention&#xA;that &lt;code&gt;vcl_hit&lt;/code&gt; required some custom VCL for checking the cached object&amp;rsquo;s&#xA;&lt;code&gt;cacheable&lt;/code&gt; attribute for the purpose of identifying whether it&amp;rsquo;s a hit-for-pass&#xA;object or not.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this &lt;code&gt;vcl_hit&lt;/code&gt; code logic is still part of the free Varnish software,&#xA;but it has been made redundant by Fastly&amp;rsquo;s version.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;error-handling&#34;&gt;Error Handling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In Varnish you can trigger an error using the &lt;code&gt;error&lt;/code&gt; directive, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;error 900 &amp;quot;Not found&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s common to use the made-up &lt;code&gt;9xx&lt;/code&gt; range for these error triggers&#xA;(900, 901, 902 etc).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once executed, Varnish will switch to the &lt;code&gt;vcl_error&lt;/code&gt; state, where you can&#xA;construct a &lt;em&gt;synthetic&lt;/em&gt; error to be returned (or do some other action like set a&#xA;header and restart the request).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (obj.status == 900) {&#xA;  set obj.status = 500;&#xA;  set obj.http.Content-Type = &amp;quot;text/html&amp;quot;;&#xA;  synthetic {&amp;quot;&amp;lt;h1&amp;gt;Hmmm. Something went wrong.&amp;lt;/h1&amp;gt;&amp;quot;};&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we construct a synthetic error response where the status&#xA;code is a &lt;code&gt;500 Internal Server Error&lt;/code&gt;, we set the content-type to HTML and then&#xA;we use the &lt;code&gt;synthetic&lt;/code&gt; directive to manually construct some HTML to be the&#xA;&amp;lsquo;body&amp;rsquo; of our response. Finally we execute &lt;code&gt;return(deliver)&lt;/code&gt; to jump over to the&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to send a synthetic JSON response (maybe your Fastly service is&#xA;fronting an API that returns JSON), then this is possible:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (obj.status == 401) {&#xA;  set obj.http.Content-Type = &amp;quot;application/json&amp;quot;;&#xA;  set obj.http.WWW-Authenticate = &amp;quot;Basic realm=Secured&amp;quot;;&#xA;&#xA;  synthetic &amp;quot;{&amp;quot; +&#xA;    &amp;quot;%22error%22: %22401 Unauthorized%22&amp;quot; +&#xA;  &amp;quot;}&amp;quot;;&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We discuss JSON generation in more detail &lt;a href=&#34;#logging-memory-exhaustion&#34;&gt;later&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;unexpected-state-change&#34;&gt;Unexpected State Change&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now, I wanted to talk briefly about error handling because there are situations&#xA;where an error can occur, and it can cause Varnish to change to an &lt;em&gt;unexpected&lt;/em&gt;&#xA;state. I&amp;rsquo;ll give a real-life example of this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We noticed that we were getting a raw &lt;code&gt;503 Backend Unavailable&lt;/code&gt; error from&#xA;Varnish displayed to our customers. This is odd? We have VCL code in &lt;code&gt;vcl_fetch&lt;/code&gt;&#xA;(the state that you move to once the response from the origin has been received&#xA;by Fastly/Varnish) which checks the response status code for a 5xx and handles&#xA;the error there. Why didn&amp;rsquo;t that code run?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, it turns out that &lt;code&gt;vcl_fetch&lt;/code&gt; is only executed if the backend/origin was&#xA;considered &amp;lsquo;available&amp;rsquo; (i.e. Fastly could make a request to it). In this&#xA;scenario what happened was that our backend &lt;em&gt;was&lt;/em&gt; available but there was a&#xA;network issue with one of Fastly&amp;rsquo;s POPs which meant it was unable to route&#xA;certain traffic, resulting in the backend appearing as &amp;lsquo;unavailable&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what happens in those scenarios? In this case Varnish won&amp;rsquo;t execute&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; because of course no request was ever made (how could Varnish make a&#xA;request if it thinks the backend is unavailable), so instead Varnish jumps from&#xA;&lt;code&gt;vcl_miss&lt;/code&gt; (where the request to the backend would be initiated from) to&#xA;&lt;code&gt;vcl_error&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means in order to handle that very specific error scenario, we&amp;rsquo;d need to&#xA;have similar code for checking the status code (and trying to serve stale, see&#xA;later in this article for more information on that) within &lt;code&gt;vcl_error&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;update-2019-11-07&#34;&gt;UPDATE 2019.11.07&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Fastly&amp;rsquo;s Fiddle tool now shows a compiler error that suggests 8xx-9xx are codes&#xA;used internally by Fastly and that we should use the 6xx range instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;According to Fastly the 900 code is often a dangeous code to use in custom VCL.&#xA;In 8xx territory, they have a special case attached to 801, which is used for&#xA;redirects to TLS in the case of requests coming in on HTTP. So if you manually&#xA;trigger an 801, weird stuff happens.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;6xx and 7xx are clean. 600, 601 and 750 are by far the most popular codes used&#xA;in customer configs apparently. In the standards range, we have a special case&#xA;attached to 550, for some reason, lost in the mists of time, but otherwise&#xA;errors in the standards range are interpreted as specified in the IETF spec&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;state-variables&#34;&gt;State Variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each Varnish &amp;lsquo;state&amp;rsquo; has a set of built-in variables you can use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a list of available variables and which states they&amp;rsquo;re available to:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Based on Varnish 3.0 (which is the only explicit documentation I could find on&#xA;this), although you can see in various request flow diagrams for different&#xA;Varnish versions the variables listed next to each state. But&#xA;&lt;a href=&#34;http://book.varnish-software.com/3.0/VCL_functions.html#variable-availability-in-vcl&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt;&#xA;was the first explicit list I found. Fastly themselves recommend &lt;a href=&#34;https://varnish-cache.org/docs/2.1/reference/vcl.html#variables&#34; target=&#34;_blank&#34;&gt;this Varnish&#xA;reference&lt;/a&gt;&#xA;but that doesn&amp;rsquo;t indicate which variables are read vs write.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h3 id=&#34;update-2020-12-11&#34;&gt;UPDATE 2020.12.11&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The Fastly &amp;lsquo;Developer Hub&amp;rsquo; now has an official reference 🎉&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://developer.fastly.com/reference/vcl/variables/&#34; target=&#34;_blank&#34;&gt;developer.fastly.com/reference/vcl/variables/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a quick key for the various states:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;R&lt;/em&gt;: recv&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;F&lt;/em&gt;: fetch&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;P&lt;/em&gt;: pass&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;M&lt;/em&gt;: miss&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;H&lt;/em&gt;: hit&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;E&lt;/em&gt;: error&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;D&lt;/em&gt;: deliver&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;I&lt;/em&gt;: pipe&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;#&lt;/em&gt;: hash&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th align=&#34;left&#34;&gt;&lt;/th&gt;&#xA;&lt;th&gt;R&lt;/th&gt;&#xA;&lt;th&gt;F&lt;/th&gt;&#xA;&lt;th&gt;P&lt;/th&gt;&#xA;&lt;th&gt;M&lt;/th&gt;&#xA;&lt;th&gt;H&lt;/th&gt;&#xA;&lt;th&gt;E&lt;/th&gt;&#xA;&lt;th&gt;D&lt;/th&gt;&#xA;&lt;th&gt;I&lt;/th&gt;&#xA;&lt;th&gt;#&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;req.*&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;bereq.*&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;obj.hits&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R&lt;/td&gt;&#xA;&lt;td&gt;R&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;obj.ttl&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;obj.grace&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;obj.*&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;beresp.*&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td align=&#34;left&#34;&gt;&lt;code&gt;resp.*&lt;/code&gt;&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;R/W&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;td&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For the values assigned to each variable:&lt;br&gt;&#xA;&lt;code&gt;R/W&lt;/code&gt; is &amp;ldquo;Read and Write&amp;rdquo;,&lt;br&gt;&#xA;and &lt;code&gt;R&lt;/code&gt; is &amp;ldquo;Read&amp;rdquo;&lt;br&gt;&#xA;and &lt;code&gt;W&lt;/code&gt; is &amp;ldquo;Write&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to realise that the above matrix is based on Varnish and not&#xA;Fastly&amp;rsquo;s version of Varnish. But there&amp;rsquo;s only one difference between them, which&#xA;is the response object &lt;code&gt;resp&lt;/code&gt; isn&amp;rsquo;t available within &lt;code&gt;vcl_error&lt;/code&gt; when using&#xA;Fastly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you&amp;rsquo;re dealing with &lt;code&gt;vcl_recv&lt;/code&gt; you pretty much only ever interact with the&#xA;&lt;code&gt;req&lt;/code&gt; object. You generally will want to manipulate the incoming request&#xA;&lt;em&gt;before&lt;/em&gt; doing anything else.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the only other reason for setting data on the &lt;code&gt;req&lt;/code&gt; object is when you&#xA;want to keep track of things (because, as we can see from the above table&#xA;matrix, the &lt;code&gt;req&lt;/code&gt; object is available to R/W from &lt;em&gt;all&lt;/em&gt; available states).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once a lookup in the cache is complete (i.e. &lt;code&gt;vcl_hash&lt;/code&gt;) we&amp;rsquo;ll end up in either&#xA;&lt;code&gt;vcl_miss&lt;/code&gt; or &lt;code&gt;vcl_hit&lt;/code&gt;. If you end up in &lt;code&gt;vcl_hit&lt;/code&gt;, then generally you&amp;rsquo;ll look&#xA;at and work with the &lt;code&gt;obj&lt;/code&gt; object (this &lt;code&gt;obj&lt;/code&gt; is what is pulled from the cache -&#xA;so you&amp;rsquo;ll check properties such as &lt;code&gt;obj.cacheable&lt;/code&gt; for dealing with things like&#xA;&amp;lsquo;hit-for-pass&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you were to end up at &lt;code&gt;vcl_miss&lt;/code&gt; instead, then you&amp;rsquo;ll probably want to&#xA;manipulate the &lt;code&gt;bereq&lt;/code&gt; object and not the &lt;code&gt;req&lt;/code&gt; object because manipulating the&#xA;&lt;code&gt;req&lt;/code&gt; object doesn&amp;rsquo;t affect the request that will shortly be made to the origin.&#xA;If you decide at this last moment you want to send an additional header to the&#xA;origin, then you would set that header on the &lt;code&gt;bereq&lt;/code&gt; and that would mean the&#xA;request to origin would include that header.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is where understanding the various state variables can be useful,&#xA;as you might want to modify the &lt;code&gt;req&lt;/code&gt; object for the sake of &amp;lsquo;persisting&amp;rsquo; a&#xA;change to another state, where as &lt;code&gt;bereq&lt;/code&gt; modification will only live for the&#xA;lifetime of the &lt;code&gt;vcl_miss&lt;/code&gt; subroutine.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once a request is made, the content is copied into the &lt;code&gt;beresp&lt;/code&gt; variable and&#xA;made available within the &lt;code&gt;vcl_fetch&lt;/code&gt; state. You would likely want to modify&#xA;this object in order to change its ttl or cache headers because this is the last&#xA;chance you have to do that before the content is stored in the cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, the &lt;code&gt;beresp&lt;/code&gt; object is copied into &lt;code&gt;resp&lt;/code&gt; and that is what&amp;rsquo;s made&#xA;available within the &lt;code&gt;vcl_deliver&lt;/code&gt; state. This is the last chance you have for&#xA;manipulating the response that the client will receive. Changes you make to this&#xA;object doesn&amp;rsquo;t affect what was stored in the cache (because that time,&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt;, has already passed).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;anonymous-objects&#34;&gt;Anonymous Objects&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are two scenarios in which a &lt;code&gt;pass&lt;/code&gt; occurs. One is that you &lt;code&gt;return(pass)&lt;/code&gt;&#xA;from &lt;code&gt;vcl_recv&lt;/code&gt; explicitly, and the other is that &lt;code&gt;vcl_recv&lt;/code&gt; executes a&#xA;&lt;code&gt;return(lookup)&lt;/code&gt; (which is the default behaviour) and the lookup results in a&#xA;hit-for-pass object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In both cases, an anonymous object is created, and the next customer-accessible&#xA;VCL hook that will run is &lt;code&gt;vcl_pass&lt;/code&gt;. Because the object is anonymous, any&#xA;changes you make to it in &lt;code&gt;vcl_fetch&lt;/code&gt; are not persisted beyond that one client&#xA;request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only difference between the behaviour of a &lt;code&gt;return(pass)&lt;/code&gt; from &lt;code&gt;vcl_recv&lt;/code&gt;&#xA;and a &lt;code&gt;return(pass)&lt;/code&gt; resulting from a hit-for-pass in the cache, is that&#xA;&lt;code&gt;req.digest&lt;/code&gt; will be set. Fastly&amp;rsquo;s internal varnish engineering team state that&#xA;&lt;code&gt;req.digest&lt;/code&gt; is not an identifier for the object but rather a property of the&#xA;request, which has been set simply because the request went through the hash&#xA;process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An early &lt;code&gt;return(pass)&lt;/code&gt; from &lt;code&gt;vcl_recv&lt;/code&gt; doesn&amp;rsquo;t go through &lt;code&gt;vcl_hash&lt;/code&gt; and so no&#xA;hash (&lt;code&gt;req.digest&lt;/code&gt;) is added to the anonymous object. If there is a hash&#xA;(&lt;code&gt;req.digest&lt;/code&gt;) available on the object inside of &lt;code&gt;vcl_pass&lt;/code&gt;, it doesn&amp;rsquo;t mean you&#xA;retain a reference to the cache object.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;forcing-request-to-origin&#34;&gt;Forcing Request to Origin&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;While we&amp;rsquo;re discussing state variables, I recently (2020.03.04) discovered that&#xA;the &lt;code&gt;req&lt;/code&gt; object has a set of properties exposed that will enable you to force a&#xA;request through to the origin while allowing the response to be cached.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These properties are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.hash_always_miss&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;req.hash_ignore_busy&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You would need to set them to &lt;code&gt;true&lt;/code&gt; in &lt;code&gt;vcl_recv&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set req.hash_always_miss = true;&#xA;set req.hash_ignore_busy = true;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to realize that getting a request through to the origin is a&#xA;&lt;em&gt;different&lt;/em&gt; scenario to using &lt;code&gt;return(pass)&lt;/code&gt; in either &lt;code&gt;vcl_recv&lt;/code&gt; and&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; (as might have been your first thought).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of &lt;code&gt;vcl_recv&lt;/code&gt; a &lt;code&gt;return(pass)&lt;/code&gt; would cause the request to not only&#xA;bypass a cache lookup (thus going to origin to fetch the content), but also the&#xA;primary/fetching node wouldn&amp;rsquo;t have executed &lt;code&gt;vcl_fetch&lt;/code&gt;! The fetching of&#xA;content would have happened on the delivery node and so another client (if they&#xA;reached a different delivery node, might end up at the fetching node and find no&#xA;cached content there).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of &lt;code&gt;vcl_fetch&lt;/code&gt; a &lt;code&gt;return(pass)&lt;/code&gt; would mean the response isn&amp;rsquo;t&#xA;cached. So you can see how both the &lt;code&gt;vcl_recv&lt;/code&gt; and &lt;code&gt;vcl_fetch&lt;/code&gt; states executing&#xA;&lt;code&gt;return(pass)&lt;/code&gt; isn&amp;rsquo;t the same thing as letting a request bypass the cache &lt;em&gt;but&lt;/em&gt;&#xA;still having the origin response be cached!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When using &lt;code&gt;hash_always_miss&lt;/code&gt; we&amp;rsquo;re causing the cache lookup to think it got a&#xA;miss (rather than &amp;lsquo;passing&amp;rsquo; it altogether). So this means features such as&#xA;&lt;a href=&#34;#request-collapsing&#34;&gt;request collapsing&lt;/a&gt; are still intact.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where as the use of &lt;code&gt;hash_ignore_busy&lt;/code&gt; &lt;em&gt;disables&lt;/em&gt; request collapsing and so this&#xA;will result in a &amp;lsquo;last cached wins&amp;rsquo; scenario (e.g. if you have two requests now&#xA;going simultaneously to origin, whichever responds first will be cached but then&#xA;the one that responds last will overwrite the first cached response).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/collapse.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/collapse.webp&#34; alt=&#34;collapse&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;request collapsing in action ^^&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;clustering&#34;&gt;Clustering&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now that we know there are state variables available, and we understand&#xA;generally when and why we would use them, let&amp;rsquo;s now consider the problem of&#xA;&amp;lsquo;clustering&amp;rsquo;. Because if you don&amp;rsquo;t understand Fastly&amp;rsquo;s clustering design, then&#xA;you&amp;rsquo;ll end up in a situation where data you&amp;rsquo;re setting on these variables are&#xA;being lost and you won&amp;rsquo;t know why.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To help make clustering easier to understand I&amp;rsquo;ve created a diagram (below) of&#xA;some Varnish internal &amp;lsquo;states&amp;rsquo;. In this diagram are two sections &amp;lsquo;cluster edge&amp;rsquo;&#xA;and &amp;lsquo;cluster shield&amp;rsquo;. Both represent individual cache servers running Varnish,&#xA;but for the sake of simplicity I&amp;rsquo;ve omitted most of the Varnish states from the&#xA;&amp;lsquo;cluster shield&amp;rsquo; node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;div id=&#34;varnish-request-flow&#34;&gt;&lt;/div&gt;&#xA;&lt;a href=&#34;/assets/img/varnish-request-flow.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/varnish-request-flow.png&#34; alt=&#34;varnish request flow&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this diagram does not cover &lt;em&gt;all&lt;/em&gt; the states available to Fastly&amp;rsquo;s&#xA;implementation of Varnish. There is also &lt;code&gt;vcl_log&lt;/code&gt; which is executed after&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt;. There is also &lt;code&gt;vcl_error&lt;/code&gt; which can be triggered from multiple&#xA;other state functions.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The directional lines drawn on the diagram represent various request flows you&#xA;&lt;em&gt;might&lt;/em&gt; see in a typical Varnish implementation (definitely in my case at any&#xA;rate). Of course these aren&amp;rsquo;t the &lt;em&gt;only&lt;/em&gt; request flows you might see; there are&#xA;numerous ways for a request to flow through the Varnish state machine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Before we jump into some request flow examples (and then further onto the&#xA;discussion of clustering), let&amp;rsquo;s take a moment to define some terminology that&#xA;will help us throughout the rest of this post&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The terminology I will use from here on, will be as follows:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;delivery node (i.e. the &amp;lsquo;cluster edge&amp;rsquo;)&lt;/li&gt;&#xA;&lt;li&gt;fetching node (i.e. the &amp;lsquo;cluster shield&amp;rsquo;)&lt;/li&gt;&#xA;&lt;li&gt;primary node (i.e. fetching node for a specific object)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;To explain the terminology:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a cache server within a Fastly POP receives a request for an object, that&#xA;server is &amp;lsquo;acting&amp;rsquo; as the delivery node (as it will be the server responsible&#xA;for returning a response to the client).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the delivery node has an empty cache, then the request won&amp;rsquo;t immediately&#xA;reach the origin. Instead the hash key for the requested resource/object will be&#xA;used to identify a &amp;ldquo;primary&amp;rdquo; node, which is the node that will &lt;em&gt;always&lt;/em&gt; (†)&#xA;&amp;lsquo;act&amp;rsquo; as a fetching node (i.e. it&amp;rsquo;s the server that will be responsible for&#xA;handling the request for that specific resource/object).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† well, &lt;em&gt;almost&lt;/em&gt; always. Except when the delivery node that ends up being&#xA;selected &lt;em&gt;is&lt;/em&gt; the &amp;ldquo;primary&amp;rdquo; node. Then the primary node is no longer acting as&#xA;a fetching node, as it&amp;rsquo;s forced to act as a delivery node instead. Requiring a&#xA;&amp;ldquo;secondary&amp;rdquo; node to act as a backup for those scenarios.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In some cases you&amp;rsquo;ll notice a &amp;ldquo;fetching node&amp;rdquo; being refered to as a &amp;ldquo;cluster&#xA;node&amp;rdquo;. this can help to understand some of Fastly&amp;rsquo;s APIs (e.g. &lt;code&gt;is_cluster&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;delivery-node-request-flow&#34;&gt;Delivery node request flow&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now consider a &lt;em&gt;simple&lt;/em&gt; example request flow using that diagram. For this&#xA;example, a node has been selected within the POP and it will start to process&#xA;the request (so the server node is &amp;lsquo;acting&amp;rsquo; as the delivery node).&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;client issues a request (and delivery node identified).&lt;/li&gt;&#xA;&lt;li&gt;request is received and &lt;code&gt;vcl_recv&lt;/code&gt; is called.&lt;/li&gt;&#xA;&lt;li&gt;imagine the &lt;code&gt;vcl_recv&lt;/code&gt; logic triggers the &lt;code&gt;return(pass)&lt;/code&gt; directive.&lt;/li&gt;&#xA;&lt;li&gt;the state will change to &lt;code&gt;vcl_pass&lt;/code&gt; (skipping cache lookup).&lt;/li&gt;&#xA;&lt;li&gt;after &lt;code&gt;vcl_pass&lt;/code&gt; has completed, the request flows through to origin.&lt;/li&gt;&#xA;&lt;li&gt;the origin responds and the state changes to &lt;code&gt;vcl_fetch&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;modifications to the response object will be cached.&lt;/li&gt;&#xA;&lt;li&gt;after &lt;code&gt;vcl_fetch&lt;/code&gt; has completed, response content is stored in the cache.&lt;/li&gt;&#xA;&lt;li&gt;the state changes to &lt;code&gt;vcl_deliver&lt;/code&gt; (modifications here are sent to client).&lt;/li&gt;&#xA;&lt;li&gt;response is sent back to the client.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s just one example route that could be taken, and I conveniently chose that&#xA;example because it meant only requiring one cache server to serve the response&#xA;to a client (the fetching node, and the concept of clustering, didn&amp;rsquo;t come into&#xA;effect in that example).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;example-without-clustering&#34;&gt;Example without Clustering&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s important to understand though is the fact that Fastly&amp;rsquo;s infrastructure&#xA;does mean (in specific scenarios) a request could indeed be handled by &lt;em&gt;two&lt;/em&gt;&#xA;separate cache servers. The initial cache server (the delivery node), and then&#xA;potentially a second cache server (the fetching node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When that happens, it is referred to as &amp;ldquo;clustering&amp;rdquo; but to more easily&#xA;understand clustering, let&amp;rsquo;s consider what happens if it &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt; exist&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Without clustering what happens is this: the cache server that gets the request&#xA;will generate a &amp;lsquo;hash key&amp;rsquo; based upon the requested URL host and path. That hash&#xA;key is then used to identify the resource in the cache that resides on the&#xA;server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the cache doesn&amp;rsquo;t contain the requested resource, then the cache server will&#xA;allow the request to flow through to the origin server which will respond with&#xA;the appropriate content and the cache will be populated with that content for&#xA;the next time that resource is requested.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This all works, &lt;strong&gt;but here&amp;rsquo;s the problem&amp;hellip;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A Fastly POP contains 64 individual caching servers. All of them have a unique&#xA;cache. That means every single cache server would at some point have to go back&#xA;to the origin for the same resource that was already cached at a different cache&#xA;server. That&amp;rsquo;s not an efficient system design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To solve that problem, Fastly came up with the concept of Clustering.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clustering is the coordination of &lt;em&gt;two&lt;/em&gt; nodes within a POP to fulfill a request.&#xA;The following image (and explanation) should help to clarify why this design is&#xA;much better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;div id=&#34;fastly-pop&#34;&gt;&lt;/div&gt;&#xA;&lt;a href=&#34;/assets/img/fastly-pop.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/fastly-pop.png&#34; alt=&#34;fastly pop&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With clustering, the hash key for a requested resource is used, firstly to&#xA;lookup the content in the cache of the current server (e.g. the delivery node),&#xA;but also to identify a specific node that will be used for fetching the content&#xA;from origin (and is referred to as the &amp;ldquo;primary&amp;rdquo; node, or &lt;em&gt;fetching&lt;/em&gt; node) for&#xA;when the content cannot be found in the delivery node&amp;rsquo;s cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This design means that multiple requests to different delivery nodes can all go&#xA;to the same &amp;ldquo;primary&amp;rdquo; cache node (e.g. the fetching node) to &lt;em&gt;fetch&lt;/em&gt; the content&#xA;from the origin if they themselves didn&amp;rsquo;t have the requested resource cached.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This way, if we had ten requests for the same resource, and each request ended&#xA;up at a different delivery node (and each delivery node failed to locate the&#xA;resource in their cache) then only one of those ten requests would need to go to&#xA;the origin (via the fetching node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When the fetching node gets the content from the origin, it sticks the response&#xA;in its cache and the response is sent back to the delivery node which also&#xA;caches the response but only in memory (not on disk!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But how does the fetching node stop all ten requests from each delivery node&#xA;from reaching the origin, I hear you ask? Well, this is what&amp;rsquo;s referred to as&#xA;&amp;ldquo;request collapsing&amp;rdquo;. It&amp;rsquo;s the process of blocking in-flight requests (for the&#xA;same resource) until at least one request for that resource has completed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In &lt;em&gt;most&lt;/em&gt; cases the cache server that initially receives the request will not be&#xA;the &amp;ldquo;primary&amp;rdquo;. But not always. Sometimes the cache server that initially handles&#xA;the incoming client request &lt;em&gt;IS&lt;/em&gt; the primary (e.g. what was the fetching node)!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why is that you ask? It&amp;rsquo;s because the server that the request is initially sent&#xA;to is picked at &lt;em&gt;random&lt;/em&gt;. So what happens in that scenario?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where Fastly introduce the concept of a &amp;ldquo;secondary&amp;rdquo; node. It exists much&#xA;like the &amp;ldquo;primary&amp;rdquo; does, to act as a cache layer before a request reaches the&#xA;origin and exists for those specific times where the primary node is forced to&#xA;act as the delivery node (e.g. just because a primary node is acting as a&#xA;delivery shouldn&amp;rsquo;t mean it goes directly to the origin; the &amp;ldquo;secondary&amp;rdquo; helps to&#xA;prevent that).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for the most part you don&amp;rsquo;t need to worry too much about primary and&#xA;secondary nodes, and only really need to know about the general concept of&#xA;clustering consisting of a delivery node and a fetching node.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;fetching-node-request-flow&#34;&gt;Fetching node request flow&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now go back to &lt;a href=&#34;#varnish-request-flow&#34;&gt;the earlier &amp;lsquo;request flow&amp;rsquo; diagram&lt;/a&gt;. Try&#xA;to imagine a request reaching a delivery node, and the node having an empty&#xA;cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;d find the state changes would be &lt;code&gt;vcl_recv&lt;/code&gt;, &lt;code&gt;vcl_hash&lt;/code&gt;, &lt;code&gt;vcl_miss&lt;/code&gt; (the&#xA;red one, which is an internal fastly operation that checks to see if A.&#xA;clustering is enabled, which it is by default and also B. is the current server&#xA;a fetching node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case, clustering is enabled and we&amp;rsquo;re not on the fetching node. So the&#xA;request flows from the delivery node to the fetching node where that server&amp;rsquo;s&#xA;cache is checked and either the &lt;code&gt;vcl_hit&lt;/code&gt; or &lt;code&gt;vcl_miss&lt;/code&gt; states will be&#xA;triggered.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, because any node within the cluster can be selected as the delivery node,&#xA;it means there &lt;em&gt;could&lt;/em&gt; be an in-memory copy of the cached content existing&#xA;there. In that scenario the request would yield a cache HIT and thus only that&#xA;one cache server is handling the request (e.g. no need to then go to the&#xA;primary/fetching node).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;why-are-there-different-states-running-on-different-nodes&#34;&gt;Why are there different states running on different nodes?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One other thing to be aware of is that when a request flows from a delivery node&#xA;to a fetching node (because the content isn&amp;rsquo;t found in the cache on the delivery&#xA;node) the request will have to flow &lt;em&gt;back&lt;/em&gt; to the delivery node in order for the&#xA;client to receive a response!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think about it, if the request is proxied from a delivery node to a fetching&#xA;node, then it isn&amp;rsquo;t possible for the fetching node to respond to the client&#xA;because the caller wasn&amp;rsquo;t the client but the delivery node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why for most standard request flows you&amp;rsquo;ll find that the &lt;code&gt;vcl_recv&lt;/code&gt;,&#xA;&lt;code&gt;vcl_hash&lt;/code&gt;, &lt;code&gt;vcl_pass&lt;/code&gt;, &lt;code&gt;vcl_deliver&lt;/code&gt; states are all handled by the delivery&#xA;node, while &lt;code&gt;vcl_miss&lt;/code&gt;, &lt;code&gt;vcl_hit&lt;/code&gt; and &lt;code&gt;vcl_fetch&lt;/code&gt; are documented as being&#xA;executed on the fetching node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because when the delivery node&amp;rsquo;s cache lookup fails to find any cached&#xA;content, the request is proxied to the fetching node where it will again attempt&#xA;a cache lookup. From that point (let&amp;rsquo;s say no content was cached there either)&#xA;the fetching node will execute a &lt;code&gt;vcl_miss&lt;/code&gt;, then &lt;code&gt;vcl_fetch&lt;/code&gt; and ultimately&#xA;it&amp;rsquo;ll &lt;em&gt;have&lt;/em&gt; to stop there and return the response to the delivery node so it&#xA;can change to the &lt;code&gt;vcl_deliver&lt;/code&gt; state in order to send the response to the&#xA;client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now as far as Fastly’s documentation is concerned (as of 2019.11.08) they A.)&#xA;don&amp;rsquo;t document the fact that &lt;code&gt;vcl_hash&lt;/code&gt; runs on the delivery node, and B.) is&#xA;incorrect with regards to &lt;code&gt;vcl_pass&lt;/code&gt;, which they claim runs on the fetching node&#xA;(which it doesn&amp;rsquo;t, for the most part, as it is designed to &lt;a href=&#34;#breaking-clustering&#34;&gt;break&#xA;clustering&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I pointed Fastly to their documentation, their response was:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“if you pass in recv, you’re saying no to cache lookup, and no to request&#xA;collapsing, so there’s no reason to cluster the request”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Which was then followed with&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“big sigh, ok, I’m filing an issue”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You definitely &lt;em&gt;can&lt;/em&gt; end up in &lt;code&gt;vcl_pass&lt;/code&gt; on a fetching node, but admittedly it&#xA;happens less frequently because you would have to &lt;code&gt;return(pass)&lt;/code&gt; from either&#xA;&lt;code&gt;vcl_hit&lt;/code&gt; or &lt;code&gt;vcl_miss&lt;/code&gt; (and that’s not a typical state change flow for most&#xA;people).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/this-is-fine.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/this-is-fine.webp&#34; alt=&#34;this is fine&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;^^ whenever I learn something new about Fastly&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;breaking-clustering&#34;&gt;Breaking clustering&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If we&amp;rsquo;re on a delivery node and we have a state that executes a&#xA;&lt;code&gt;return(restart)&lt;/code&gt; directive, then we actually &lt;em&gt;break&lt;/em&gt; &amp;lsquo;clustering&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means the request will go back to the delivery node and that node will&#xA;handle the full request cycle. This is done for reasons of performance, such as&#xA;finding stale content in the &lt;code&gt;vcl_deliver&lt;/code&gt; state on the delivery node and&#xA;wanting to serve that stale content †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† we&amp;rsquo;ll learn about &lt;a href=&#34;#6&#34;&gt;serving stale&lt;/a&gt; later.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now go back to &lt;a href=&#34;#varnish-request-flow&#34;&gt;the earlier &amp;lsquo;request flow&amp;rsquo; diagram&lt;/a&gt;. Try&#xA;to imagine a request reaching a delivery node, and the node having an empty&#xA;cache, but also that clustering has been broken (due to a &lt;code&gt;return(restart)&lt;/code&gt;&#xA;being triggered in &lt;code&gt;vcl_deliver&lt;/code&gt; on the delivery node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;d find the state changes would be &lt;code&gt;vcl_recv&lt;/code&gt;, &lt;code&gt;vcl_hash&lt;/code&gt;, &lt;code&gt;vcl_miss&lt;/code&gt; (the&#xA;red one, which is an internal fastly operation that checks to see if A.&#xA;clustering is enabled, which it is by default and also B. is the current server&#xA;a fetching node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case, clustering is enabled and we&amp;rsquo;re not on the fetching node. So the&#xA;request flows from the delivery node to the fetching node where that server&amp;rsquo;s&#xA;cache is checked and either the &lt;code&gt;vcl_hit&lt;/code&gt; or &lt;code&gt;vcl_miss&lt;/code&gt; states will be&#xA;triggered. But ultimately the request will flow back to the delivery node, where&#xA;we&amp;rsquo;ll reach its &lt;code&gt;vcl_deliver&lt;/code&gt; state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there the &lt;code&gt;vcl_deliver&lt;/code&gt; triggers a &lt;code&gt;return(restart)&lt;/code&gt;, which as we now know&#xA;breaks clustering, and so we end up back in &lt;code&gt;vcl_recv&lt;/code&gt; of the delivery node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point the request will reach &lt;code&gt;vcl_hash&lt;/code&gt; and we might find we again reach&#xA;&lt;code&gt;vcl_miss&lt;/code&gt; (the &amp;lsquo;internal&amp;rsquo; red one), but this time clustering is broken so we&#xA;now reach your own code&amp;rsquo;s &lt;code&gt;vcl_miss&lt;/code&gt; of the delivery node and thus the delivery&#xA;node will proxy the request onto the origin and then execute the &lt;code&gt;vcl_fetch&lt;/code&gt;&#xA;state (instead of those steps happening on the fetching node).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;avoid-breaking-clustering&#34;&gt;Avoid breaking clustering&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So what if breaking clustering is something you want to avoid? Let me start by&#xA;saying I personally have never found a reason to avoid breaking clustering when&#xA;executing a &lt;code&gt;return(restart)&lt;/code&gt; but that doesn&amp;rsquo;t mean good reasons don&amp;rsquo;t exist.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to avoid breaking the clustering process you&amp;rsquo;ll need to utilize the&#xA;&lt;code&gt;Fastly-Force-Shield: 1&lt;/code&gt; request header. This header will re-enable clustering&#xA;so that we again use multiple server nodes within a POP when executing the&#xA;different VCL subroutine states.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;legacy-terminology&#34;&gt;Legacy terminology&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Notice the naming of this header (&lt;code&gt;Fastly-Force-Shield&lt;/code&gt;), it uses what&amp;rsquo;s&#xA;considered by Fastly now to be &lt;em&gt;legacy&lt;/em&gt; terminology.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To explain: Fastly has historically used the term &amp;ldquo;shield&amp;rdquo; to describe the&#xA;fetching node, as per the concept we now refer to as &amp;ldquo;clustering&amp;rdquo;. But it wasn&amp;rsquo;t&#xA;always called clustering.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Long ago clustering was referred to as &amp;ldquo;shielding&amp;rdquo;, but in more recent times&#xA;Fastly designed an extension to clustering which became a new feature also&#xA;called &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/shielding&#34; target=&#34;_blank&#34;&gt;Shielding&lt;/a&gt;.&#xA;Fastly changed the old &amp;ldquo;shielding&amp;rdquo; terminology to &amp;ldquo;clustering&amp;rdquo;, thus allowing&#xA;the new Shielding feature to be more easily distinguished (even though the&#xA;underlying concepts are closely related).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;the-problem-of-persisting-state&#34;&gt;The problem of persisting state&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, so two more &lt;em&gt;really&lt;/em&gt; important things to be aware of at this point:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Data added to the &lt;code&gt;req&lt;/code&gt; object &lt;em&gt;cannot&lt;/em&gt; persist across boundaries (except for&#xA;when initially moving from the edge to the cluster).&lt;/li&gt;&#xA;&lt;li&gt;Data added to the &lt;code&gt;req&lt;/code&gt; object &lt;em&gt;can&lt;/em&gt; persist a restart, but &lt;em&gt;not&lt;/em&gt; when they&#xA;are added from the cluster environment.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;For number 1. that means: &lt;code&gt;req&lt;/code&gt; data you set in &lt;code&gt;vcl_recv&lt;/code&gt; and &lt;code&gt;vcl_hash&lt;/code&gt; will&#xA;be available in states like &lt;code&gt;vcl_pass&lt;/code&gt; and &lt;code&gt;vcl_miss&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For number 2. that means: if you were in &lt;code&gt;vcl_deliver&lt;/code&gt; and you set a value on&#xA;&lt;code&gt;req&lt;/code&gt; and then triggered a restart, the value would be available in &lt;code&gt;vcl_recv&lt;/code&gt;.&#xA;Yet, if you were in &lt;code&gt;vcl_miss&lt;/code&gt; for example and you set &lt;code&gt;req.http.X-Foo&lt;/code&gt; and&#xA;let&amp;rsquo;s say in &lt;code&gt;vcl_fetch&lt;/code&gt; you look at the response from the origin and see the&#xA;origin sent you back a 5xx status, you might decide you want to restart the&#xA;request and try again. But if you were expecting &lt;code&gt;X-Foo&lt;/code&gt; to be set on the &lt;code&gt;req&lt;/code&gt;&#xA;object when the code in &lt;code&gt;vcl_recv&lt;/code&gt; was re-executed, you&amp;rsquo;d be wrong. That&amp;rsquo;s&#xA;because the header was set on the &lt;code&gt;req&lt;/code&gt; object while it was in a state that is&#xA;executed on a fetching node; and so the &lt;code&gt;req&lt;/code&gt; data set there doesn&amp;rsquo;t persist a&#xA;restart.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Summary: modifications on the fetching node don&amp;rsquo;t persist to the delivery node.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re starting to think: &amp;ldquo;this makes things tricky&amp;rdquo;, you&amp;rsquo;d be right :-)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;#fastly-pop&#34;&gt;earlier diagram&lt;/a&gt; visualizes the approach for how a request&#xA;inside of a POP will reach a specific cache node (i.e. &amp;ldquo;clustering&amp;rdquo;) but it&#xA;doesn&amp;rsquo;t cover how&#xA;&amp;ldquo;&lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/&#34; target=&#34;_blank&#34;&gt;shielding&lt;/a&gt;&amp;rdquo; works, which&#xA;effectively is a &lt;em&gt;nested&lt;/em&gt; clustering process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s dig into Shielding next&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;shielding&#34;&gt;Shielding&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Shielding is a designated POP that a request will flow through &lt;em&gt;before&lt;/em&gt; reaching&#xA;your origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As mentioned earlier, clustering is the coordination of two nodes within a POP,&#xA;and this &amp;lsquo;clustering&amp;rsquo; happens within every POP. The shield POP is no different&#xA;from any other POP in its fundamental behaviour.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when people start talking about shielding and its &amp;ldquo;Shield POP&amp;rdquo;, you&amp;rsquo;ll&#xA;usually find the terminology of &amp;ldquo;POP&amp;rdquo; changes to &amp;ldquo;Edge POP&amp;rdquo; as a way to help&#xA;distinguish that there are two separate POPs involved in the discussion. I&#xA;personally don&amp;rsquo;t do that. I just call an Edge POP a POP and when talking about&#xA;shielding I&amp;rsquo;ll say &amp;ldquo;Shield POP&amp;rdquo;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The purpose of shielding is to give extra protection to your origin, because&#xA;multiple users will arrive at different POPs (due to their locality) and so a&#xA;POP in the UK might not have a cached object, while a POP in the USA might have&#xA;a cached version of the resource. To help prevent the UK user from making a&#xA;request back to the origin, we can select a POP nearest the origin to act as a&#xA;single point of access.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when the UK request comes through and there is no cached content within that&#xA;POP, the request wont go to origin, it&amp;rsquo;ll go to the shield POP which will&#xA;hopefully have the content cached (if not then the shield POP sends the request&#xA;onto the origin).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But ultimately the content either already cached at the shield (or is about to&#xA;be cached at the shield if it had no cache) will be bubbled back to the UK POP&#xA;where the content will be cached there as well.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there isn&amp;rsquo;t any real latency concern with using shielding because Fastly&#xA;optimizes the network BGP routing between POPs. The only thing to ensure is&#xA;that your shield POP is located next to your origin because Fastly can&amp;rsquo;t&#xA;optimize the connection from the shield POP to the origin (it can only&#xA;optimize traffic within its own network).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This also gives us extra nomenclature to distinguish POPs. Before we learnt&#xA;about shielding, we just knew there were &amp;lsquo;POPs&amp;rsquo; but now we know that with&#xA;shielding enabled we have &amp;lsquo;edge&amp;rsquo; POPs and a singular &amp;lsquo;shield&amp;rsquo; POP for a&#xA;particular Fastly service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll link &lt;a href=&#34;https://fiddle.fastlydemo.net/fiddle/72e0d619&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; to a&#xA;Fastly-Fiddle (created by a Fastly engineer) that demonstrates the&#xA;clustering/shielding flow. If that fiddle no longer exists by the time you read&#xA;this then I&amp;rsquo;ve made a copy of it in a&#xA;&lt;a href=&#34;https://gist.github.com/Integralist/c08b1ab3e9dd508b1ccc5fe768d1a9b0&#34; target=&#34;_blank&#34;&gt;gist&lt;/a&gt;.&#xA;It&amp;rsquo;s interesting to see how the various APIs for identifying a server node come&#xA;together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly we should be aware that if for some reason there is a network issue in&#xA;the region of your selected &amp;lsquo;shield&amp;rsquo; POP, then Fastly will first (from the&#xA;&amp;lsquo;edge&amp;rsquo; POP) check the health of the shield POP before forwarding the request&#xA;there. If the shield is unhealthy (e.g. maybe there is a network outage in its&#xA;region), then the request will be forwarded directly to your origin.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;caveats-of-fastly-s-shielding&#34;&gt;Caveats of Fastly&amp;rsquo;s Shielding&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;First thing to note is that if your service has a &lt;code&gt;restart&lt;/code&gt; statement, then be&#xA;warned that this doesn&amp;rsquo;t just disable clustering but also shielding. To&#xA;re-enable clustering you can use &lt;code&gt;Fastly-Force-Shield&lt;/code&gt; but there is no way to&#xA;re-enable shielding unless you manually copy/paste the relevant logic from&#xA;Fastly&amp;rsquo;s generated VCL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Be careful with changes you make to a request as they could result in the lookup&#xA;hash to change between the edge POP nodes and shield POP nodes (so it&amp;rsquo;s likely&#xA;best you make changes to the &lt;code&gt;bereq&lt;/code&gt; object in &lt;code&gt;vcl_miss&lt;/code&gt; rather than the &lt;code&gt;req&lt;/code&gt;&#xA;object within &lt;code&gt;vcl_recv&lt;/code&gt;). Also the shield POP will be using the same&#xA;Domain/Host UI configuration and so if you change the Host header, then proxying&#xA;the request from the edge POP to the shield POP would result in a breakage as&#xA;the shield POP won&amp;rsquo;t recognize the Host of the incoming request and thus will&#xA;not know which &amp;lsquo;service&amp;rsquo; to direct the request onto.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, be aware that the &amp;ldquo;backend&amp;rdquo; will change when shielding is enabled.&#xA;Traditionally (i.e. without shielding) you defined your backend with a specific&#xA;value (e.g. an S3 bucket or a domain such as &lt;code&gt;https://app.domain.com&lt;/code&gt;) and it&#xA;would stay set to that value unless you yourself implemented custom vcl logic to&#xA;change its value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But with shielding enabled, the delivery node will dynamically change the&#xA;backend to be a shield node value (as it&amp;rsquo;s effectively &lt;em&gt;always&lt;/em&gt; going to pass&#xA;through that node if there is no cached content found). Once on the delivery&#xA;node within the shield POP, &lt;em&gt;its&lt;/em&gt; &amp;ldquo;backend&amp;rdquo; value is set to whatever your actual&#xA;origin is (e.g. an S3 bucket).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, if you dynamically set your backend in VCL, be sure to A.) set it before the&#xA;fastly recv macro is executed, and B.) be sure to only set it on the shield POP&#xA;otherwise your request will go from the edge POP direct to your origin and not&#xA;your shield POP.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be careful with &amp;lsquo;shared code&amp;rsquo; (e.g. VCL code you reuse across multiple&#xA;services) because if you add a conditional such as &lt;code&gt;if (req.backend.is_shield) { /* execute code on edge POP */ }&lt;/code&gt; then this is fine when executing this code&#xA;on a service with shielding enabled, but it won&amp;rsquo;t work as intended on a&#xA;service that &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; use shielding! Because a service without shielding will&#xA;not have the backend set to a shield, so that conditional will fail to match.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s probably best to only modify your backends dynamically whilst your VCL is&#xA;executing on the shield (e.g. &lt;code&gt;if (!req.backend.is_shield)&lt;/code&gt;, maybe abstract in a&#xA;variable &lt;code&gt;declare local var.shield_node BOOL;&lt;/code&gt;) and to also only &lt;code&gt;restart&lt;/code&gt; a&#xA;request in vcl_deliver when executing on a node within the shield POP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You might also need to modify vcl_hash so that the generated hash is consistent&#xA;with the edge POP&amp;rsquo;s delivery node if your shield POP nodes happen to modify the&#xA;request! Remember that modifying either the host or the path will cause a&#xA;different cache key to be generated and so modifying that in either the edge POP&#xA;&lt;em&gt;or&lt;/em&gt; the shield POP means modifying the relevant vcl_hash subroutine so the&#xA;hashes are &lt;em&gt;consistent&lt;/em&gt; between them.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_hash {&#xA;  # we do this because we want the cache key to be identical at the edge and&#xA;  # at the shield. Because the shield rewrites req.url (but not the edge), we&#xA;  # need align vcl_hash by using the original Host and URL.&#xA;  set req.hash += req.http.X-Original-URL;&#xA;  set req.hash += req.http.X-Original-Host;&#xA;&#xA;  #FASTLY hash&#xA;&#xA;  return(hash);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;alternatively you could move rewriting of the URL to a state after the&#xA;hash lookup, such as vcl_miss (e.g. modifying the &lt;code&gt;bereq&lt;/code&gt; object).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Be careful with non-idempotent changes. For example, things like the &lt;code&gt;Vary&lt;/code&gt;&#xA;header being modified on the shield POP and then again on the edge POP, as this&#xA;&lt;em&gt;could&lt;/em&gt; result in the edge POP getting a poor HIT ratio due to the fact that the&#xA;shield has appended a header and then that header is appended again as part of&#xA;the edge POP execution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/double.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/double.webp&#34; alt=&#34;double&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consideration needs to be given to the use of &lt;code&gt;req.backend.is_shield&lt;/code&gt; when you&#xA;get a 5xx (or any other uncacheable error code) back from the origin to the&#xA;shield POP, because it means an &amp;lsquo;pass&amp;rsquo; state will be triggered. When the&#xA;response reaches the delivery node within the edge POP, the pass state will&#xA;cause clustering to be disabled and so the origin will no longer be the shield&#xA;POP (as it was at the start of the request flow).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, when enabling shielding, make sure to deploy your VCL code changes first&#xA;&lt;em&gt;before&lt;/em&gt; enabling shielding. This way you avoid a race condition whereby a&#xA;shield has old VCL (i.e. no conditional checks for either &lt;code&gt;Fastly-FF&lt;/code&gt; or&#xA;&lt;code&gt;req.backend.is_shield&lt;/code&gt;) and thus tries to do something that should only happen&#xA;on the edge cache node.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;debugging-shielding&#34;&gt;Debugging Shielding&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you want to track extra information when using shielding, then use (in&#xA;combination with either &lt;code&gt;req.backend.is_origin&lt;/code&gt; or &lt;code&gt;!req.backend.is_shield&lt;/code&gt;) the&#xA;values from &lt;code&gt;server.datacenter&lt;/code&gt; and &lt;code&gt;server.hostname&lt;/code&gt; which can help you&#xA;identify the POP as your shielding POP (remember there is only one POP that is&#xA;designated as your shield, so this can come in handy).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;remember that, although a statistically small chance, the edge POP that&#xA;is reached by a client request could be the shield POP so your mechanism for&#xA;checking if something is a shield needs to account for that scenario.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Additionally, there is &lt;a href=&#34;https://fiddle.fastlydemo.net/fiddle/d053c409&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt;&#xA;Fastly-Fiddle which clarifies the &lt;code&gt;req.backend.is_cluster&lt;/code&gt; API which actually is&#xA;different to similarly named APIs such as &lt;code&gt;req.backend.is_origin&lt;/code&gt; and&#xA;&lt;code&gt;req.backend.is_shield&lt;/code&gt;, so let&amp;rsquo;s dig into that quickly&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;is-cluster-vs-is-origin-vs-is-shield&#34;&gt;&lt;code&gt;is_cluster&lt;/code&gt; vs &lt;code&gt;is_origin&lt;/code&gt; vs &lt;code&gt;is_shield&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are a few properties hanging off the &lt;code&gt;req.backend&lt;/code&gt; object in VCL&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;is_cluster&lt;/code&gt;: indicates when the request has come from a clustering node (e.g.&#xA;fetching node).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;is_origin&lt;/code&gt;: indicates if the request will be proxied to an origin server&#xA;(e.g. your own backend application).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;is_shield&lt;/code&gt;: indicates if the request will be proxied to a shield POP (which&#xA;happens when shielding is enabled).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you try to access &lt;code&gt;is_origin&lt;/code&gt; from within the &lt;code&gt;vcl_recv&lt;/code&gt; state subroutine,&#xA;for example, it will be cause a compiler error. This is because that API is only&#xA;available to fetching nodes (and specifically only states that would result in a&#xA;request being proxied, meaning although &lt;code&gt;vcl_hit&lt;/code&gt; runs on a fetching node, that&#xA;state would not have access to &lt;code&gt;is_origin&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So depending on what you&amp;rsquo;re trying to verify, it might be preferable to use the&#xA;negated &lt;code&gt;is_shield&lt;/code&gt; approach for checking if the request is going to be proxied&#xA;to origin or a shield pop node.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;undocumented-apis&#34;&gt;Undocumented APIs&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.http.Fastly-FF&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4 id=&#34;req-http-fastly-ff&#34;&gt;&lt;code&gt;req.http.Fastly-FF&lt;/code&gt;&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;The first API we&amp;rsquo;ll look at is: &lt;code&gt;req.http.Fastly-FF&lt;/code&gt; which indicates if a&#xA;request has come from a Fastly server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth mentioning that it&amp;rsquo;s not really safe to use &lt;code&gt;req.http.Fastly-FF&lt;/code&gt;&#xA;because it can be set by a client making the request, and so there is no&#xA;guarantee of its accuracy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, the use of &lt;code&gt;req.http.Fastly-FF&lt;/code&gt; can become complicated if you have&#xA;multiple Fastly services &lt;em&gt;chained&lt;/em&gt; one after the other because it means&#xA;&lt;code&gt;Fastly-FF&lt;/code&gt; could be set by a Fastly service not owned by you (i.e. the reported&#xA;value is misleading).&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;fastly-info-is-cluster-edge-and-fastly-info-is-cluster-shield&#34;&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt; and &lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;With regards to &lt;code&gt;is_cluster&lt;/code&gt; there are also some additional &lt;em&gt;undocumented&lt;/em&gt; APIs&#xA;we can use:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; if the current &lt;code&gt;vcl_&lt;/code&gt; state subroutine&#xA;is running on a delivery node.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: &lt;code&gt;true&lt;/code&gt; if the current &lt;code&gt;vcl_&lt;/code&gt; state subroutine&#xA;is running on a fetching node.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to realize that &lt;code&gt;is_cluster_edge&lt;/code&gt; will only ever report true from&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt;, as (just like &lt;code&gt;req.backend.is_cluster&lt;/code&gt;) we have to come &lt;em&gt;from&lt;/em&gt; a&#xA;clustering/fetching node first. The &lt;code&gt;vcl_recv&lt;/code&gt; state can&amp;rsquo;t know if it&amp;rsquo;s going to&#xA;go into clustering at that stage of the request hence it reports as &lt;code&gt;false&lt;/code&gt;&#xA;there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With &lt;code&gt;vcl_fetch&lt;/code&gt; it knows it has come from the delivery node and thus we&amp;rsquo;ve gone&#xA;into &amp;lsquo;clustering&amp;rsquo; mode, hence it can report &lt;code&gt;is_cluster_shield&lt;/code&gt; as &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So as a more fleshed out example, if we tried to log all three cluster APIs in&#xA;all VCL subroutines (and imagine we have clustering enabled with Fastly, which&#xA;is the default behaviour), then we would find the following results&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_recv&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.backend.is_cluster&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_hash&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.backend.is_cluster&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_miss&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.backend.is_cluster&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: yes&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_fetch&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.backend.is_cluster&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: yes&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_deliver&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;req.backend.is_cluster&lt;/code&gt;: yes&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_edge&lt;/code&gt;: yes&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly_info.is_cluster_shield&lt;/code&gt;: no&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4 id=&#34;fastly-ff-visits-this-service&#34;&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;The last undocumented API we&amp;rsquo;ll look at will be &lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;&#xA;which indicates for each server node how many times it has seen the request&#xA;currently being handled. This helps us to execute a piece of code only once&#xA;(maybe authentication needs to happen at the edge only once).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see what this looks like in a clustering scenario like shown a moment&#xA;ago&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_recv&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;: &lt;code&gt;0&lt;/code&gt; (we&amp;rsquo;re on a delivery node and we&amp;rsquo;ve never seen this request before)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_hash&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;: &lt;code&gt;0&lt;/code&gt; (we&amp;rsquo;re still on the same delivery node so the reported value is the same)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_miss&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;: &lt;code&gt;1&lt;/code&gt; (we&amp;rsquo;ve jumped to the fetching node so we know it&amp;rsquo;s been seen once before somewhere)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_fetch&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;: &lt;code&gt;1&lt;/code&gt; (we&amp;rsquo;re on the same fetching node so the value is reported the same)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;vcl_deliver&lt;/code&gt;:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt;: &lt;code&gt;0&lt;/code&gt; (we&amp;rsquo;re back onto the original delivery node so the value is reported as 0 again).&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Even if you restart the request, the value of the variable will go back to zero&#xA;on the delivery node. See &lt;a href=&#34;https://fiddle.fastlydemo.net/fiddle/913c397d&#34; target=&#34;_blank&#34;&gt;this&#xA;fiddle&lt;/a&gt; for an example.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when you introduce shielding you&amp;rsquo;ll find that the value increases to &lt;code&gt;2&lt;/code&gt;&#xA;when we reach &lt;code&gt;vcl_recv&lt;/code&gt; on the delivery node inside the shield POP.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The following code snippet demonstrates how to run code either on the edge POP&#xA;or the shield POP whilst also protecting against the scenario where the code is&#xA;copy/pasted into a service that doesn&amp;rsquo;t have shielding enabled (see also:&#xA;&lt;a href=&#34;#caveats-of-fastly-s-shielding&#34;&gt;Caveats of Fastly&amp;rsquo;s Shielding&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.backend.is_shield || fastly.ff.visits_this_service &amp;lt; 2) {&#xA;  # edge POP&#xA;}&#xA;&#xA;if (!req.backend.is_shield &amp;amp;&amp;amp; fastly.ff.visits_this_service &amp;gt;= 2) {&#xA;  # shield POP&#xA;}&#xA;&#xA;# one liner for variable assignment&#xA;if(req.backend.is_shield, &amp;quot;edge&amp;quot;, if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be careful with shielding because if the shield POP got a 5xx from the&#xA;origin then it&amp;rsquo;ll trigger an internal PASS state and so once we&amp;rsquo;re back at the&#xA;delivery node inside the edge POP, if we try to check if the backend is the&#xA;&amp;lsquo;shield&amp;rsquo; using &lt;code&gt;req.backend.is_shield&lt;/code&gt; then it won&amp;rsquo;t match because the origin&#xA;for the edge POP will no longer be the shield (clustering has been disabled&#xA;because of the &amp;lsquo;pass state&amp;rsquo;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;breadcrumb-trail&#34;&gt;Breadcrumb Trail&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now consider a requirement for creating a breadcrumb trail of the various&#xA;states a request moves through (we&amp;rsquo;ll do this by defining a &lt;code&gt;X-VCL-Route&lt;/code&gt; HTTP&#xA;header). Implementing this feature is great for debugging purposes as it&amp;rsquo;ll&#xA;validate your understanding of how your requests are flowing through the varnish&#xA;state machine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/debugging.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/debugging.webp&#34; alt=&#34;debugging&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First I&amp;rsquo;m going to show you the basic outline of the various vcl state&#xA;subroutines and a set of function calls. Next I&amp;rsquo;ll show you the code for those&#xA;function calls and talk through what they&amp;rsquo;re doing.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the code examples will be simplified for sake of brevity and to&#xA;highlight the calls related to the breadcrumb trail functionality.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In essence though, we&amp;rsquo;re using the understanding we have for the delivery node&#xA;and fetching node &lt;em&gt;boundaries&lt;/em&gt; and ensuring that while on the fetching node we&#xA;track information in Varnish objects (e.g. things like &lt;code&gt;req&lt;/code&gt;, &lt;code&gt;obj&lt;/code&gt;, &lt;code&gt;beresp&lt;/code&gt;&#xA;etc) that are able to persist crossing those boundaries.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means when going from &lt;code&gt;vcl_fetch&lt;/code&gt; to &lt;code&gt;vcl_deliver&lt;/code&gt; we can&amp;rsquo;t track&#xA;information on the &lt;code&gt;req&lt;/code&gt; object because it&amp;rsquo;ll be lost when we move over to&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; and so we track it in the &lt;code&gt;beresp&lt;/code&gt; object that &lt;code&gt;vcl_fetch&lt;/code&gt; has&#xA;access to. We do this because we know that &lt;code&gt;beresp&lt;/code&gt; is &lt;em&gt;copied&lt;/em&gt; over to&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; and exposed inside of &lt;code&gt;vcl_deliver&lt;/code&gt; as the &lt;code&gt;resp&lt;/code&gt; object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similarly for &lt;code&gt;vcl_error&lt;/code&gt;, we track information in its &lt;code&gt;obj&lt;/code&gt; reference because&#xA;when we move over to &lt;code&gt;vcl_deliver&lt;/code&gt; the &lt;code&gt;obj&lt;/code&gt; reference will be copied over as&#xA;the &lt;code&gt;resp&lt;/code&gt; object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From &lt;code&gt;vcl_deliver&lt;/code&gt; we&amp;rsquo;re then free to copy the tracked information from the&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; header (stored in the &lt;code&gt;resp&lt;/code&gt; object) into the &lt;code&gt;req&lt;/code&gt; object (in&#xA;case we need to restart the request and keep tracking information after a&#xA;restart).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that &lt;code&gt;vcl_pass&lt;/code&gt; and &lt;code&gt;vcl_miss&lt;/code&gt; both run on the fetching node and so&#xA;again tracking information on the &lt;code&gt;req&lt;/code&gt; object won&amp;rsquo;t persist when moving over to&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt;. That&amp;rsquo;s why although we track information on the &lt;code&gt;req&lt;/code&gt; object&#xA;within those state subroutines, we in fact (once we&amp;rsquo;ve reached &lt;code&gt;vcl_fetch&lt;/code&gt;) copy&#xA;those tracked values into the &lt;code&gt;beresp&lt;/code&gt; object available to &lt;code&gt;vcl_fetch&lt;/code&gt; for the&#xA;reasons we described earlier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, enough talking, let&amp;rsquo;s see the code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;include &amp;quot;debug_info&amp;quot;&#xA;&#xA;sub vcl_recv {&#xA;  call debug_info_recv;&#xA;&#xA;  #FASTLY recv&#xA;&#xA;  return(lookup);&#xA;}&#xA;&#xA;sub vcl_hash {&#xA;  #FASTLY hash&#xA;&#xA;  set req.hash += req.url;&#xA;  set req.hash += req.http.host;&#xA;&#xA;  call debug_info_hash;&#xA;&#xA;  return(hash);&#xA;}&#xA;&#xA;&#xA;sub vcl_miss {&#xA;  #FASTLY miss&#xA;&#xA;  call debug_info_miss;&#xA;&#xA;  return(fetch);&#xA;}&#xA;&#xA;sub vcl_pass {&#xA;  #FASTLY pass&#xA;&#xA;  call debug_info_pass;&#xA;}&#xA;&#xA;sub vcl_fetch {&#xA;  #FASTLY fetch&#xA;&#xA;  call debug_info_fetch;&#xA;&#xA;  return(deliver);&#xA;}&#xA;&#xA;sub vcl_error {&#xA;  #FASTLY error&#xA;&#xA;  call debug_info_error;&#xA;&#xA;  return(deliver);&#xA;}&#xA;&#xA;sub vcl_deliver {&#xA;  call debug_info_deliver;&#xA;&#xA;  ...other code...&#xA;&#xA;  call debug_info_send;&#xA;&#xA;  #FASTLY deliver&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The thing to look out for (in the above code) are the function calls that start&#xA;with &lt;code&gt;debug_info_&lt;/code&gt; (e.g. &lt;code&gt;debug_info_recv&lt;/code&gt;, &lt;code&gt;debug_info_hash&lt;/code&gt; &amp;hellip;etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These functions are all defined within a VCL file called &lt;code&gt;debug_info.vcl&lt;/code&gt;, which&#xA;we import at the top of the example code (i.e. &lt;code&gt;include &amp;quot;debug_info&amp;quot;&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once that file is imported we will have access to the various &lt;code&gt;debug_info_&lt;/code&gt;&#xA;functions that the VCL state subroutines are calling.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The other thing you&amp;rsquo;ll notice is that we have &lt;em&gt;two&lt;/em&gt; separate function calls&#xA;within &lt;code&gt;vcl_deliver&lt;/code&gt;. We have the standard &lt;code&gt;debug_info_deliver&lt;/code&gt; (as described a&#xA;moment ago), but we also have &lt;code&gt;debug_info_send&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;debug_info_send&lt;/code&gt; isn&amp;rsquo;t strictly necessary (e.g. the code within it could be&#xA;moved inside of &lt;code&gt;debug_info_deliver&lt;/code&gt;) but I wanted to distinguish between&#xA;functions that &lt;em&gt;collected&lt;/em&gt; data and this function that was responsible for&#xA;&lt;em&gt;sending&lt;/em&gt; the collected data back within the response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now take a look at that &lt;code&gt;debug_info&lt;/code&gt; VCL and then we&amp;rsquo;ll explain what the&#xA;code is doing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# This file sets a X-VCL-Route response header.&#xA;#&#xA;# X-VCL-Route has a baseline format of:&#xA;#&#xA;# pop: &amp;lt;value&amp;gt;, node: &amp;lt;value&amp;gt;, state: &amp;lt;value&amp;gt;, host: &amp;lt;value&amp;gt;, path: &amp;lt;value&amp;gt;&#xA;#&#xA;# pop  = the POP where the request is currently passing through.&#xA;# node  = whether the cache node is a delivery node or fetching node&#xA;# state = internal fastly variable that reports state flow (req waited for collapsing or clustered).&#xA;# host  = the full host name, without the path or query parameters.&#xA;# path   = the full path, including query parameters.&#xA;#&#xA;# Additional to this baseline we include information relevant to the subroutine state.&#xA;&#xA;sub debug_info_recv {&#xA;  declare local var.context STRING;&#xA;  set var.context = &amp;quot;&amp;quot;;&#xA;&#xA;  if (req.restarts &amp;gt; 0) {&#xA;    set var.context = req.http.X-VCL-Route + &amp;quot;, &amp;quot;;&#xA;  }&#xA;&#xA;  set req.http.X-VCL-Route = var.context + &amp;quot;VCL_RECV(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_edge, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_hash {&#xA;  set req.http.X-VCL-Route = req.http.X-VCL-Route + &amp;quot;, VCL_HASH(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_edge, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_miss {&#xA;  set req.http.X-PreFetch-Miss = &amp;quot;, VCL_MISS(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    &amp;quot; [&amp;quot; server.datacenter &amp;quot;, &amp;quot; server.hostname &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_&amp;quot; + if(fastly_info.is_cluster_shield, &amp;quot;shield&amp;quot;, &amp;quot;edge&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + bereq.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + bereq.url +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_pass {&#xA;  set req.http.X-PreFetch-Pass = &amp;quot;, &amp;quot; if(fastly_info.state ~ &amp;quot;^HITPASS&amp;quot;, &amp;quot;VCL_HIT&amp;quot;, &amp;quot;VCL_PASS&amp;quot;) &amp;quot;(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_&amp;quot; + if(fastly_info.is_cluster_shield, &amp;quot;shield&amp;quot;, &amp;quot;edge&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_fetch {&#xA;  set beresp.http.X-Track-VCL-Route = req.http.X-VCL-Route;&#xA;  set beresp.http.X-PreFetch-Pass = req.http.X-PreFetch-Pass;&#xA;  set beresp.http.X-PreFetch-Miss = req.http.X-PreFetch-Miss;&#xA;  set beresp.http.X-PostFetch = &amp;quot;, VCL_FETCH(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_&amp;quot; + if(fastly_info.is_cluster_shield, &amp;quot;shield&amp;quot;, &amp;quot;edge&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;status: &amp;quot; + beresp.status + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;stale: &amp;quot; + if(stale.exists, &amp;quot;exists&amp;quot;, &amp;quot;none&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    if(beresp.http.Cache-Control ~ &amp;quot;private&amp;quot;, &amp;quot;cache_control: private, return: pass&amp;quot;, &amp;quot;return: deliver&amp;quot;) +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_error {&#xA;  declare local var.error_page BOOL;&#xA;  set var.error_page = false;&#xA;&#xA;  set obj.http.X-VCL-Route = req.http.X-VCL-Route + &amp;quot;, VCL_ERROR(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_&amp;quot; + if(fastly_info.is_cluster_shield, &amp;quot;shield&amp;quot;, &amp;quot;edge&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;status: &amp;quot; + obj.status + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;stale: &amp;quot; + if(stale.exists, &amp;quot;exists&amp;quot;, &amp;quot;none&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;sub debug_info_deliver {&#xA;  # only track the previous route flow if we&#39;ve come from vcl_fetch&#xA;  # otherwise we&#39;ll end up displaying the uncached request flow as&#xA;  # part of this cache hit request flow (which would be confusing).&#xA;  if (resp.http.X-Track-VCL-Route &amp;amp;&amp;amp; fastly_info.state ~ &amp;quot;^(MISS|PASS)&amp;quot;) {&#xA;    set req.http.X-VCL-Route = resp.http.X-Track-VCL-Route;&#xA;&#xA;    if (resp.http.X-PreFetch-Pass) {&#xA;      set req.http.X-VCL-Route = req.http.X-VCL-Route + resp.http.X-PreFetch-Pass;&#xA;    }&#xA;&#xA;    if (resp.http.X-PreFetch-Miss) {&#xA;      set req.http.X-VCL-Route = req.http.X-VCL-Route + resp.http.X-PreFetch-Miss;&#xA;    }&#xA;&#xA;    if (resp.http.X-PostFetch) {&#xA;      set req.http.X-VCL-Route = req.http.X-VCL-Route + resp.http.X-PostFetch;&#xA;    }&#xA;  } elseif (fastly_info.state ~ &amp;quot;^ERROR&amp;quot;) {&#xA;    # otherwise track in the request object any request flow information that &#xA;    # has occurred from an error request flow &#xA;    # which should include either the original vcl_fetch flow or the vcl_hit flow.&#xA;    set req.http.X-VCL-Route = resp.http.X-VCL-Route;&#xA;  } elseif (fastly_info.state ~ &amp;quot;^HIT($|-)&amp;quot;) {&#xA;    # otherwise track the initial vcl_hit request flow.&#xA;    set req.http.X-VCL-Route = req.http.X-VCL-Route + &amp;quot;, VCL_HIT(&amp;quot; +&#xA;      &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;      if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;      + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;      &amp;quot;node: cluster_shield, &amp;quot; +&#xA;      &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;      &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;      &amp;quot;path: &amp;quot; + req.url + &amp;quot;, &amp;quot; +&#xA;      &amp;quot;status: &amp;quot; + resp.status + &amp;quot;, &amp;quot; +&#xA;      &amp;quot;cacheable: true, &amp;quot; +&#xA;      &amp;quot;return: deliver&amp;quot; +&#xA;      &amp;quot;)&amp;quot;;&#xA;  }&#xA;&#xA;  # used to extend the baseline X-VCL-Route (set below)&#xA;  declare local var.context STRING;&#xA;  set var.context = &amp;quot;&amp;quot;;&#xA;&#xA;  # there is one state subroutine that we have no way of tracking information&#xA;  # for: vcl_hit # this is because the only object we have available with R/W access&#xA;  # is the req object # and modifications to the req object don&#39;t persiste from&#xA;  # cluster node to edge node (e.g. vcl_deliver) # this means we need to utilise&#xA;  # fastly&#39;s internal state to see if we came from vcl_hit.&#xA;  #&#xA;  # we also use this internal state variable to help identify other states &#xA;  # progressions such as&#xA;  # STALE (stale content found in case of an error) and ERROR &#xA;  # (we&#39;ve arrived to vcl_deliver from vcl_error).&#xA;  #&#xA;  # Documentation (fastly_info.state):&#xA;  # https://support.fastly.com/hc/en-us/community/posts/360040168391/comments/360004718351&#xA;  if (fastly_info.state ~ &amp;quot;^HITPASS&amp;quot;) {&#xA;    set var.context = &amp;quot;, cacheable: uncacheable, return: pass&amp;quot;;&#xA;  } elseif (fastly_info.state ~ &amp;quot;^ERROR&amp;quot;) {&#xA;    set var.context = &amp;quot;, custom_error_page: &amp;quot; + resp.http.CustomErrorPage;&#xA;  }&#xA;&#xA;  set req.http.X-VCL-Route = req.http.X-VCL-Route + &amp;quot;, VCL_DELIVER(&amp;quot; +&#xA;    &amp;quot;pop: &amp;quot; + if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;    if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)) &#xA;    + &amp;quot; [&amp;quot; + server.datacenter + &amp;quot;, &amp;quot; + server.hostname + &amp;quot;], &amp;quot; +&#xA;    &amp;quot;node: cluster_edge, &amp;quot; +&#xA;    &amp;quot;state: &amp;quot; + fastly_info.state + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;host: &amp;quot; + req.http.host + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;path: &amp;quot; + req.url + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;status: &amp;quot; + resp.status + &amp;quot;, &amp;quot; +&#xA;    &amp;quot;stale: &amp;quot; + if(stale.exists, &amp;quot;exists&amp;quot;, &amp;quot;none&amp;quot;) +&#xA;    var.context +&#xA;    &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;# this subroutine must be placed BEFORE the vcl_deliver macro `#FASTLY deliver`&#xA;# otherwise the setting of Fastly-Debug within this subroutine will have no effect.&#xA;sub debug_info_send {&#xA;  unset resp.http.X-Track-VCL-Route;&#xA;  unset resp.http.X-VCL-Route;&#xA;  unset resp.http.X-PreFetch-Miss;&#xA;  unset resp.http.X-PreFetch-Pass;&#xA;  unset resp.http.X-PostFetch;&#xA;&#xA;  if (req.http.X-Debug) {&#xA;    # ensure that when Fastly&#39;s own VCL executes it will be able to identify&#xA;    # the Fastly-Debug request header as enabled.&#xA;    set req.http.Fastly-Debug = &amp;quot;true&amp;quot;;&#xA;&#xA;    # other useful debug information&#xA;    set resp.http.Fastly-State = fastly_info.state;&#xA;    set resp.http.X-VCL-Route = req.http.X-VCL-Route;&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So I&amp;rsquo;ve already summarized the basic approach (i.e. ensure we set tracking&#xA;information in Varnish objects that we know persist the boundary changes), but&#xA;there are some interesting bits to take away from this code still&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Within &lt;code&gt;debug_info_recv&lt;/code&gt;, because a request can be restarted, the breadcrumb&#xA;trail may need to repeat the VCL states. So for example if a request was&#xA;restarted we would want to see &lt;code&gt;VCL_RECV(...)&lt;/code&gt; twice in the output to indicate&#xA;that this was the flow of the request. To account for that I use a &lt;code&gt;var.context&lt;/code&gt;&#xA;variable to prepend the information from &lt;em&gt;before&lt;/em&gt; the request to the new&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; header being created now the request has restarted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next you&amp;rsquo;ll notice that we have a strange expression which we&amp;rsquo;re assigning to a&#xA;&lt;code&gt;pop&lt;/code&gt; field. This field represents whether the request is being executed at an&#xA;&amp;lsquo;edge&amp;rsquo; POP or a &amp;lsquo;shield&amp;rsquo; POP (in the case that the Fastly service has shielding&#xA;enabled)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if(req.backend.is_shield, &amp;quot;edge&amp;quot;, &#xA;if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We use the &lt;code&gt;req.backend.is_shield&lt;/code&gt; API to tell us if the server is going to send&#xA;the request to a shield POP or not, but unfortunately it&amp;rsquo;s not as straight&#xA;forward as just saying &amp;ldquo;ok &lt;code&gt;is_shield&lt;/code&gt; is false so we must be on a node within&#xA;the shield POP already&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason being, if the Fastly service &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; have shielding enabled then&#xA;&lt;code&gt;req.backend.is_shield&lt;/code&gt; will &lt;em&gt;always&lt;/em&gt; return false! So that&amp;rsquo;s why we have that&#xA;nested conditional check&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if(fastly.ff.visits_this_service &amp;lt; 2, &amp;quot;edge&amp;quot;, &amp;quot;shield&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Instead of just printing &lt;code&gt;shield&lt;/code&gt; when &lt;code&gt;req.backend.is_shield&lt;/code&gt; is false we will&#xA;now first check &lt;code&gt;fastly.ff.visits_this_service&lt;/code&gt; (which we &lt;a href=&#34;#fastly-ff-visits-this-service&#34;&gt;discussed&#xA;earlier&lt;/a&gt;). This says &amp;ldquo;ok, if the returned value&#xA;is less than two we know that we must be running within an edge POP, because if&#xA;shielding was enabled and we were on a shield POP currently then the number of&#xA;&amp;lsquo;views&amp;rsquo; would be three or more at this point&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although I don&amp;rsquo;t demonstrate it here in this example code, &lt;code&gt;debug_info_hash&lt;/code&gt;&#xA;might need an extra conditional header check added to it to prevent tracking the&#xA;&lt;code&gt;vcl_hash&lt;/code&gt; execution. The reason you might want to do that is because &lt;code&gt;vcl_hash&lt;/code&gt;&#xA;is &lt;em&gt;always&lt;/em&gt; executed (even though it can in some scenarios be a no-op!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, in my own VCL code at work we have a process whereby we&amp;rsquo;ll restart&#xA;a request if we have an error come back from the origin. The reason we restart&#xA;the request is so we can serve a custom error page synthetically from the edge&#xA;server. In order to do that we set a header in &lt;code&gt;vcl_deliver&lt;/code&gt; before we restart&#xA;(e.g. &lt;code&gt;X-Error&lt;/code&gt;) and then we check it from within &lt;code&gt;vcl_recv&lt;/code&gt; only if the&#xA;&lt;code&gt;req.restarts == 1&lt;/code&gt;. From that point in &lt;code&gt;vcl_recv&lt;/code&gt; if &lt;code&gt;X-Error&lt;/code&gt; is set we&amp;rsquo;ll&#xA;trigger &lt;code&gt;vcl_error&lt;/code&gt; by calling the &lt;code&gt;error&lt;/code&gt; directive, and within &lt;code&gt;vcl_error&lt;/code&gt;&#xA;we&amp;rsquo;ll construct our synthetic custom error page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the problem we have is that in the final &lt;code&gt;X-VCL-Route&lt;/code&gt; sent back in the&#xA;response we&amp;rsquo;ll see &lt;code&gt;vcl_hash&lt;/code&gt; in the flow just after the second &lt;code&gt;vcl_recv&lt;/code&gt;&#xA;(which happens because of the restart in order to handle the custom error page&#xA;logic), and that just &amp;hellip;looks weird because it suggests to a viewer that&#xA;&lt;code&gt;vcl_hash&lt;/code&gt; had some sort of &lt;em&gt;purpose&lt;/em&gt; for running, but it doesn&amp;rsquo;t!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to avoid recording the &lt;code&gt;vcl_hash&lt;/code&gt; execution I wrap the tracking code in a&#xA;check for the &lt;code&gt;X-Error&lt;/code&gt; header (e.g. &lt;code&gt;if (!req.http.X-BF-Error) { track the execution }&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In &lt;code&gt;debug_info_fetch&lt;/code&gt; you&amp;rsquo;ll see that I don&amp;rsquo;t assign to a &lt;code&gt;X-VCL-Route&lt;/code&gt; header&#xA;on the &lt;code&gt;beresp&lt;/code&gt; object but a new &lt;code&gt;X-Track-VCL-Route&lt;/code&gt; header. The reason for this&#xA;is because the &lt;code&gt;beresp&lt;/code&gt; object is going to be placed into the Varnish cache&#xA;system once &lt;code&gt;vcl_fetch&lt;/code&gt; has finished executing and we need to be careful about&#xA;setting &lt;code&gt;X-VCL-Route&lt;/code&gt; there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for the concern is due to &lt;em&gt;new&lt;/em&gt; client requests. Imagine we set the&#xA;tracking information onto the actual &lt;code&gt;X-VCL-Route&lt;/code&gt; header on the &lt;code&gt;beresp&lt;/code&gt; (which&#xA;will be cached).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a new request is received for that same resource we&amp;rsquo;ll go to &lt;code&gt;vcl_hit&lt;/code&gt;&#xA;because the resource is found in the cache and from there we&amp;rsquo;ll end up at&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; which would normally just check for a &lt;code&gt;X-VCL-Route&lt;/code&gt; on the &lt;code&gt;resp&lt;/code&gt;&#xA;object it has been passed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in this scenario the &lt;code&gt;resp&lt;/code&gt; object is the object pulled from the Varnish&#xA;cache and so we might end up including the &lt;em&gt;uncached&lt;/em&gt; request flow in the final&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; header sent back for this secondary request!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That would be wrong because the secondary request should only report a &lt;code&gt;recv &amp;gt; hash &amp;gt; hit &amp;gt; deliver&lt;/code&gt; and not &lt;code&gt;recv &amp;gt; hash &amp;gt; miss &amp;gt; fetch &amp;gt; recv &amp;gt; hash &amp;gt; hit &amp;gt; deliver&lt;/code&gt; (which is what would happen otherwise!). See how easy it is for things&#xA;to get dangerous and confusing!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that in mind if we look at &lt;code&gt;debug_info_deliver&lt;/code&gt; we&amp;rsquo;ll see that we only&#xA;track the &amp;lsquo;uncached&amp;rsquo; request flow &lt;em&gt;if&lt;/em&gt; we can tell that we actually came from a&#xA;cache MISS state&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (resp.http.X-Track-VCL-Route &amp;amp;&amp;amp; fastly_info.state ~ &amp;quot;^MISS&amp;quot;) &#xA;{ track the data that was stored in X-Track VCL-Route }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If you want more information on &lt;code&gt;fastly_info.state&lt;/code&gt; see &lt;a href=&#34;https://community.fastly.com/t/useful-variables-to-log/303/3&#34; target=&#34;_blank&#34;&gt;this community&#xA;comment&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also see in that same conditional block we then reconstruct a&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; from the various temporary headers, such as &lt;code&gt;X-PreFetch-Pass&lt;/code&gt;,&#xA;&lt;code&gt;X-PreFetch-Miss&lt;/code&gt; and &lt;code&gt;X-PostFetch&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that in &lt;code&gt;vcl_hit&lt;/code&gt; we have no object that we can track information on&#xA;that will be persisted to the delivery node where &lt;code&gt;vcl_deliver&lt;/code&gt; is executed.&#xA;This is because &lt;code&gt;vcl_hit&lt;/code&gt; can go straight to &lt;code&gt;vcl_deliver&lt;/code&gt; and there&amp;rsquo;s no&#xA;inbetween state like &lt;code&gt;vcl_fetch&lt;/code&gt; where we can borrow a Varnish object for&#xA;tracking purposes like we do with &lt;code&gt;vcl_miss&lt;/code&gt; and &lt;code&gt;vcl_pass&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to solve that problem you&amp;rsquo;ll see that we check to see if we came from a cache&#xA;HIT state&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;fastly_info.state ~ &amp;quot;^HIT($|-)&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this will catch multiple types of hit flows, such as &lt;code&gt;HIT&lt;/code&gt; or&#xA;&lt;code&gt;HIT-CLUSTER&lt;/code&gt; or &lt;code&gt;HIT-STALE-CLUSTER&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Finally, in &lt;code&gt;debug_info_send&lt;/code&gt; you&amp;rsquo;ll see that we make sure to &lt;code&gt;unset&lt;/code&gt; any&#xA;temporary response headers (e.g. &lt;code&gt;X-Track-VCL-Route&lt;/code&gt;) so it doesn&amp;rsquo;t confuse&#xA;people scanning the response headers we send back. We also don&amp;rsquo;t send this debug&#xA;information back to the client unless they ask for it, which they can do by&#xA;providing a &lt;code&gt;req.http.X-Debug&lt;/code&gt; request header.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One interesting thing to note there is that in order to get Fastly to send back&#xA;its own debug information the user needs to provide a &lt;code&gt;Fastly-Debug&lt;/code&gt; request&#xA;header, but to avoid having to rely on that knowledge we provide our own&#xA;&lt;code&gt;X-Debug&lt;/code&gt; (which we tell our engineers about) so they only have to remember one&#xA;simpler request header to enable not only our own debugging information but&#xA;Fastly&amp;rsquo;s as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order then for the Fastly debug information to be included we have to do two&#xA;things:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;manually &lt;code&gt;set req.http.Fastly-Debug = &amp;quot;true&amp;quot;;&lt;/code&gt; in our VCL code.&lt;/li&gt;&#xA;&lt;li&gt;ensure our &lt;code&gt;debug_info_send&lt;/code&gt; is executed &lt;em&gt;before&lt;/em&gt; the &lt;code&gt;#FASTLY deliver&lt;/code&gt; macro&#xA;(which is where they execute their &lt;code&gt;Fastly-Debug&lt;/code&gt; logic).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;OK, let&amp;rsquo;s go back and revisit &lt;code&gt;vcl_error&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;vcl_error&lt;/code&gt; subroutine is a tricky one because it exists on &lt;em&gt;both&lt;/em&gt; the&#xA;delivery node and the fetching node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning if you execute &lt;code&gt;error 401&lt;/code&gt; from &lt;code&gt;vcl_recv&lt;/code&gt;, then &lt;code&gt;vcl_error&lt;/code&gt; will&#xA;execute in the context of the delivery node; whereas if you executed an &lt;code&gt;error&lt;/code&gt;&#xA;from a fetching node state like &lt;code&gt;vcl_fetch&lt;/code&gt;, then &lt;code&gt;vcl_error&lt;/code&gt; would execute in&#xA;the context of the fetching node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning, how you transition information between &lt;code&gt;vcl_error&lt;/code&gt; and &lt;code&gt;vcl_deliver&lt;/code&gt;&#xA;could depend on whether you&amp;rsquo;re on a delivery node or a fetching node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why when on what are typically considered the fetching nodes, I don&amp;rsquo;t&#xA;hardcode them a such. I use the following conditional check&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;node: cluster_&amp;quot; + if(fastly_info.is_cluster_shield, &amp;quot;shield&amp;quot;, &amp;quot;edge&amp;quot;) + &amp;quot;, &amp;quot; +&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;this check means if the request is restarted, which we know this causes&#xA;Fastly&amp;rsquo;s clustering behaviour to stop and for the request to flow through the&#xA;same delivery node for all states, then we can change the reported node to be&#xA;the delivery node instead of a fetching node for states such as MISS/PASS/FETCH.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this conditional check could be improved by also checking for the&#xA;existence of the &lt;code&gt;Fastly-Force-Shield&lt;/code&gt; header (which we talked about earlier).&#xA;This is because if someone uses that header then it would force Fastly&amp;rsquo;s&#xA;clustering behaviour to not be stopped.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To help explain this I&amp;rsquo;m going to give another &lt;em&gt;real&lt;/em&gt; example, where I wanted to&#xA;lookup some content in our cache and if it didn&amp;rsquo;t exist I wanted to restart the&#xA;request and use a different origin server to serve the content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this I expected the route to go from &lt;code&gt;vcl_recv&lt;/code&gt;, to &lt;code&gt;vcl_hash&lt;/code&gt; and the&#xA;lookup to fail so we would end up in &lt;code&gt;vcl_miss&lt;/code&gt;. Now from &lt;code&gt;vcl_miss&lt;/code&gt; I could&#xA;have triggered a restart, but anything I set on the &lt;code&gt;req&lt;/code&gt; object at that point&#xA;(such as any breadcrumb data appended to &lt;code&gt;X-VCL-Route&lt;/code&gt;) would have been lost as&#xA;we transitioned from the fetching node back to the delivery node (where&#xA;&lt;code&gt;vcl_recv&lt;/code&gt; is).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I needed a way to persist the &amp;ldquo;miss&amp;rdquo; breadcrumb, so instead of returning a&#xA;restart from &lt;code&gt;vcl_miss&lt;/code&gt; I would trigger a custom error such as &lt;code&gt;error 901&lt;/code&gt; and&#xA;inside of &lt;code&gt;vcl_error&lt;/code&gt; I would have the following logic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set obj.http.X-VCL-Route = req.http.X-VCL-Route;&#xA;&#xA;if (fastly_info.state ~ &amp;quot;^MISS&amp;quot;) {&#xA;  set obj.http.X-VCL-Route = obj.http.X-VCL-Route &amp;quot;,VCL_MISS(&amp;quot; req.http.host req.url &amp;quot;)&amp;quot;;&#xA;}&#xA;&#xA;set obj.http.X-VCL-Route = obj.http.X-VCL-Route &amp;quot;,VCL_ERROR&amp;quot;;&#xA;&#xA;if (obj.status == 901) {&#xA;  set obj.http.X-VCL-Route = obj.http.X-VCL-Route &amp;quot;,VCL_ERROR(status: 908, return: deliver)&amp;quot;;&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When we trigger an error an object is created for us. On that object I set our&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; and assign it whatever was inside &lt;code&gt;req.http.X-VCL-Route&lt;/code&gt; at that&#xA;time †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† which would include &lt;code&gt;vcl_recv&lt;/code&gt;, &lt;code&gt;vcl_hash&lt;/code&gt; and &lt;code&gt;vcl_miss&lt;/code&gt;. Remember the&#xA;&lt;code&gt;req&lt;/code&gt; object &lt;em&gt;does&lt;/em&gt; persist across the delivery node/fetching node boundaries,&#xA;but &lt;em&gt;only&lt;/em&gt; when going from &lt;code&gt;vcl_recv&lt;/code&gt;. After that, anything set on &lt;code&gt;req&lt;/code&gt; is&#xA;lost when crossing boundaries.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now we could have arrived at &lt;code&gt;vcl_error&lt;/code&gt; from &lt;code&gt;vcl_recv&lt;/code&gt; (e.g. if in our&#xA;&lt;code&gt;vcl_recv&lt;/code&gt; we had logic for checking Basic Authentication and none was found on&#xA;the incoming request we could decide from &lt;code&gt;vcl_recv&lt;/code&gt; to execute &lt;code&gt;error 401&lt;/code&gt;) or&#xA;we could have arrived at &lt;code&gt;vcl_error&lt;/code&gt; from &lt;code&gt;vcl_miss&lt;/code&gt; (as per our earlier&#xA;example). So we need to check the internal Fastly state to identify this, hence&#xA;checking &lt;code&gt;fastly_info.state ~ &amp;quot;^MISS&amp;quot;&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After that we append to the &lt;code&gt;obj&lt;/code&gt; object&amp;rsquo;s &lt;code&gt;X-VCL-Route&lt;/code&gt; header our current&#xA;state (i.e. so we know we came into &lt;code&gt;vcl_error&lt;/code&gt;). Finally we look at the status&#xA;on the &lt;code&gt;obj&lt;/code&gt; object and see it&amp;rsquo;s a 901 custom status code and so we append that&#xA;information in order to know what happened.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you&amp;rsquo;ll notice we don&amp;rsquo;t restart the request from &lt;code&gt;vcl_error&lt;/code&gt;, because if we&#xA;did come from &lt;code&gt;vcl_miss&lt;/code&gt; the data in &lt;code&gt;obj&lt;/code&gt; would be lost because ultimately it&#xA;was set on a fetching node (as &lt;code&gt;vcl_error&lt;/code&gt; would be running on the fetching node&#xA;when coming from &lt;code&gt;vcl_miss&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead we &lt;code&gt;return(deliver)&lt;/code&gt;, because all that data assigned to &lt;code&gt;obj&lt;/code&gt; is&#xA;guaranteed to be copied into &lt;code&gt;resp&lt;/code&gt; for us to reference when transitioning to&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; on the delivery node.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we&amp;rsquo;re at &lt;code&gt;vcl_deliver&lt;/code&gt; we continue to set breadcrumb tracking onto&#xA;&lt;code&gt;req.http.X-VCL-Route&lt;/code&gt; as we know that will persist a restart (as we&amp;rsquo;re still&#xA;going to be executing code on the delivery node).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Phew! Well, that was NOT an easy task, and if you struggled to follow along.&#xA;That&amp;rsquo;s OK because it&amp;rsquo;s hard to learn about all this stuff at once. Just keep&#xA;coming back to this post as a reference point if you need to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thankfully by going through this process there will be very little about&#xA;Varnish&amp;rsquo;s request flow that you won&amp;rsquo;t now understand or have the ability to work&#xA;around in future if the right problem scenario presents itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/genius.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/genius.webp&#34; alt=&#34;genius&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;header-overflow-errors&#34;&gt;Header Overflow Errors&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One final thing to note about building a &amp;lsquo;breadcrumb trail&amp;rsquo; like I&amp;rsquo;ve detailed&#xA;above is that you&amp;rsquo;ll need to be careful about how many times you restart your&#xA;request flow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve seen us restart our request up to three times (for multiple-backend&#xA;failover resiliency) and it has resulted in a raw Varnish error of &lt;code&gt;Header overflow&lt;/code&gt; to be returned in the response (the client won&amp;rsquo;t even record any&#xA;network data at all, it&amp;rsquo;s as if the client compleletely flatlines).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Googling around I discovered some &lt;a href=&#34;https://docs.fastly.com/en/guides/resource-limits#request-and-header-limits&#34; target=&#34;_blank&#34;&gt;Fastly&#xA;documentation&lt;/a&gt;&#xA;which makes reference to a &lt;code&gt;Header count&lt;/code&gt;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Exceeding the limit results in a Header overflow error. A small portion of&#xA;this limit is reserved for internal Fastly use, making the practical limit&#xA;closer to 85.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;To me this was quite an ambiguous statement and have the value set to &lt;code&gt;96&lt;/code&gt;&#xA;didn&amp;rsquo;t help elucidate the situation at all either. I had no idea what this&#xA;really meant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Was Fastly saying the overall request header size of &lt;code&gt;X-VCL-Route&lt;/code&gt; was too large&#xA;(hence a &lt;code&gt;400 Bad Request&lt;/code&gt; would be the typical response expected for that type&#xA;of error) or did it mean that I could only set that specific header 96 times and&#xA;I was reaching that limit due to the number of restarts (surely not?)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Even if I restarted the request flow three times, there&amp;rsquo;s only a total of&#xA;&lt;em&gt;eight&lt;/em&gt; VCL states and they don&amp;rsquo;t all get executed in a single request flow,&#xA;so that&amp;rsquo;s only a maximum of 24 times I would have called set on the&#xA;&lt;code&gt;X-VCL-Route&lt;/code&gt; header (way under the 96 limit).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Turns out it&amp;rsquo;s a bit more a broad range of possible problem causes than just&#xA;that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The official Fastly response to my question about what this documentation means&#xA;was as follows&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;header count = 96&lt;/code&gt; specifically means 96 headers can be present for an object&#xA;(this includes the request and response headers). The header overflow can be&#xA;caused by exceeding &lt;em&gt;any&lt;/em&gt; of the limits defined in the documentation&#xA;throughout the whole VCL process.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So it&amp;rsquo;s more likely that we &lt;em&gt;were&lt;/em&gt; hitting the http header size limit, but it&#xA;was being transformed into this raw Varnish error instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At any rate this is something to keep in mind and be mindful of.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;hit-for-pass&#34;&gt;Hit for Pass&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You may notice in Varnish&amp;rsquo;s built-in &lt;code&gt;vcl_fetch&lt;/code&gt; the following logic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;sub vcl_fetch {&#xA;    if (!beresp.cacheable) {&#xA;        return (pass);&#xA;    }&#xA;    if (beresp.http.Set-Cookie) {&#xA;        return (pass);&#xA;    }&#xA;    return (deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now typically when you &lt;code&gt;return(pass)&lt;/code&gt; you do that in &lt;code&gt;vcl_recv&lt;/code&gt; to indicate to&#xA;Varnish you do not want to lookup the content in the cache and to skip ahead to&#xA;fetching the content from the origin. But when you &lt;code&gt;return(pass)&lt;/code&gt; from&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; it causes a slightly different behaviour. Effectively we&amp;rsquo;re telling&#xA;Varnish we don&amp;rsquo;t want to cache the content we&amp;rsquo;ve received from the origin.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In the case of the VCL logic above, we&amp;rsquo;re not caching this content because we&#xA;can see there is a cookie set (indicating possibly unique user content).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll probably also notice in some organisation&amp;rsquo;s own custom &lt;code&gt;vcl_fetch&lt;/code&gt; the&#xA;following additional logic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;if (beresp.http.Cache-Control ~ &amp;quot;private&amp;quot;) {&#xA;  return(pass);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This content isn&amp;rsquo;t cached simply because the backend has indicated (via the&#xA;&lt;code&gt;Cache-Control&lt;/code&gt; header) that the content is &lt;code&gt;private&lt;/code&gt; and so should not be&#xA;cached.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you&amp;rsquo;ll find that even though you&amp;rsquo;ve executed a &lt;code&gt;return(pass)&lt;/code&gt; operation,&#xA;Varnish will &lt;em&gt;still&lt;/em&gt; create an object and cache it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/miss.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/miss.webp&#34; alt=&#34;miss&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The object it creates is called a &amp;ldquo;hit-for-pass&amp;rdquo; (if you look back at the Fastly&#xA;request flow diagram above you&amp;rsquo;ll see it referenced) and it is given a ttl of&#xA;120s (i.e. it&amp;rsquo;ll be cached for 120 seconds).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the ttl can be changed using vcl but it should be kept small. Varnish&#xA;implements a type known as a &amp;lsquo;duration&amp;rsquo; and takes many forms: ms&#xA;(milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks), y&#xA;(years). For example, &lt;code&gt;beresp.ttl = 1h&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason Varnish creates an object and caches it is because if it &lt;em&gt;didn&amp;rsquo;t&lt;/em&gt;,&#xA;when &lt;code&gt;return(pass)&lt;/code&gt; is executed and the content subsequently is not cached, then&#xA;if another request is made for that same resource, we would find &amp;ldquo;request&#xA;collapsing&amp;rdquo; causes a performance issue for users. What is &amp;lsquo;request collapsing&amp;rsquo; I&#xA;hear you ask? Well&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;request-collapsing&#34;&gt;Request Collapsing&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Request collapsing is where Varnish blocks requests for what looks to be the&#xA;same uncached resource. It does this in order to prevent overloading your&#xA;origin. So for example, if there are ten requests for an uncached resource,&#xA;it&amp;rsquo;ll allow one request through to origin and block the other nine until the&#xA;origin has responded and the content has been cached. The nine requests would&#xA;then get the content from the cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in the case of uncachable content (e.g. content that uses cookies typically&#xA;will contain content that is unique to the user requesting the resource) users&#xA;are blocked waiting for an existing request for that resource to complete, only&#xA;to find that as the resource is uncacheable the request needs to be made again&#xA;(this cycle would repeat for each user requesting this unique/uncacheable&#xA;resource).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;i.e. out of 10 requests for a resource that is ultimately uncacheable, the first&#xA;request would go through while nine are blocked waiting for the first request to&#xA;complete. The first request completes and oh-no, it can&amp;rsquo;t be cached, nevermind&#xA;let&amp;rsquo;s unblock the second request (while the other eight are blocked). When the&#xA;second request comes back we again realise it can&amp;rsquo;t be cached and the cycle&#xA;repeats until all ten requests have completed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As you can imagine, this is very bad because the requests for this uncachable&#xA;content has resulted in sequential processing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So when we &amp;ldquo;pass&amp;rdquo; inside of &lt;code&gt;vcl_fetch&lt;/code&gt; Varnish prevents this bad sequential&#xA;processing. It does this by creating a &amp;ldquo;hit-for-pass&amp;rdquo; object which has a short&#xA;ttl of 120s, and so for the next 120s any requests for this same resource will&#xA;&lt;em&gt;not&lt;/em&gt; result in request collapsing (i.e. user requests to origin will not be&#xA;blocked waiting for an already &amp;ldquo;in-flight&amp;rdquo; origin request to complete). Meaning,&#xA;&lt;em&gt;all&lt;/em&gt; requests will be sent straight through to the origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for this processing to work, we need &lt;code&gt;vcl_hit&lt;/code&gt; to check for a&#xA;&amp;ldquo;hit-for-pass&amp;rdquo; object. If we check Varnish&amp;rsquo;s built-in logic we can see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;sub vcl_hit {&#xA;    if (!obj.cacheable) {&#xA;        return (pass);&#xA;    }&#xA;    return (deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this does is it checks whether the object we found in the cache has the&#xA;attribute &lt;code&gt;cacheable&lt;/code&gt; set to &amp;lsquo;false&amp;rsquo;, and if it does we&amp;rsquo;ll not deliver that&#xA;cached object to the user but instead skip ahead to fetching the resource again&#xA;from origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By default this &lt;code&gt;cacheable&lt;/code&gt; attribute is set to &amp;lsquo;true&amp;rsquo;, but when Varnish&#xA;executes &lt;code&gt;return(pass)&lt;/code&gt; from inside of &lt;code&gt;vcl_fetch&lt;/code&gt; it caches the &amp;ldquo;hit-for-pass&amp;rdquo;&#xA;object with the &lt;code&gt;cacheable&lt;/code&gt; attribute set to &amp;lsquo;false&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason the ttl for a &amp;ldquo;hit-for-pass&amp;rdquo; object is supposed to be short is&#xA;because, for that period of time, your origin is susceptible to multiple&#xA;requests. So you don&amp;rsquo;t want your origin to become overloaded by lots of traffic&#xA;for uncacheable content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to note that an object can&amp;rsquo;t be &lt;em&gt;re-cached&lt;/em&gt; (let&amp;rsquo;s say the origin&#xA;no longer sends a &lt;code&gt;private&lt;/code&gt; directive) until either the hit-for-pass TTL expires&#xA;&lt;em&gt;or&lt;/em&gt; the hit-for-pass object is purged.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See &lt;a href=&#34;https://info.varnish-software.com/blog/hit-for-pass-varnish-cache&#34; target=&#34;_blank&#34;&gt;this Varnish blog&#xA;post&lt;/a&gt; for&#xA;the full details.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;serving-stale&#34;&gt;Serving Stale&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If we get a 5xx error from our origins we don&amp;rsquo;t cache them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But instead of serving that 5xx to the user (or even a custom 500 error page),&#xA;we&amp;rsquo;ll attempt to locate a &amp;lsquo;stale&amp;rsquo; version of the content and serve that to the&#xA;user instead (i.e. &amp;lsquo;stale&amp;rsquo; in this case means a resource that was requested and&#xA;cached previously, but the object was marked as being something that could be&#xA;served stale if its &amp;lsquo;stale ttl&amp;rsquo; has yet to expire).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we do this is because serving old (i.e. stale) content is better than&#xA;serving an error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/stale.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/stale.webp&#34; alt=&#34;stale&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;small class=&#34;img-caption&#34;&gt;stale content is always better, right! ^^&lt;/small&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to serve stale we need to add some conditional checks into our VCL logic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll typically notice in both &lt;code&gt;vcl_fetch&lt;/code&gt; and &lt;code&gt;vcl_deliver&lt;/code&gt; there are checks&#xA;for a 5xx status code in the response we got back from origin, and subsequently&#xA;a further check for &lt;code&gt;stale.exists&lt;/code&gt; if we found a match for a 5xx status code. It&#xA;looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you don&amp;rsquo;t have to run this code only from &lt;code&gt;vcl_deliver&lt;/code&gt;. It can be&#xA;beneficial to do this via &lt;code&gt;vcl_error&lt;/code&gt; as well because if your origin is&#xA;unreachable, then it means you&amp;rsquo;ll want to check for stale in &lt;code&gt;vcl_error&lt;/code&gt; as&#xA;well. Fastly gives an example of this in &lt;a href=&#34;https://docs.fastly.com/en/guides/serving-stale-content#serving-stale-content-on-errors&#34; target=&#34;_blank&#34;&gt;their&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;if (&amp;lt;object&amp;gt;.status &amp;gt;= 500 &amp;amp;&amp;amp; &amp;lt;object&amp;gt;.status &amp;lt; 600) {&#xA;  if (stale.exists) {&#xA;    # ...&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Where &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt; is either &lt;code&gt;beresp&lt;/code&gt; (&lt;code&gt;vcl_fetch&lt;/code&gt;) or &lt;code&gt;resp&lt;/code&gt; (&lt;code&gt;vcl_deliver&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;When looking at the value for &lt;code&gt;stale.exists&lt;/code&gt;, if it returns &amp;lsquo;true&amp;rsquo;, it is&#xA;telling us that there is an object in the cache whose ttl has expired but as far&#xA;as Varnish is concerned is still valid for serving as stale content. The way&#xA;Varnish knows whether to keep a stale object around so it can be used for&#xA;serving as stale content depends on the following settings:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;set beresp.stale_while_revalidate = &amp;lt;N&amp;gt;s;&#xA;set beresp.stale_if_error = &amp;lt;N&amp;gt;s;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Where &lt;code&gt;&amp;lt;N&amp;gt;&lt;/code&gt; is the amount of time in seconds you want to keep the object for&#xA;after its ttl has expired.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;stale_while_revalidate&lt;/code&gt;: request received, obj found in cache, but ttl has&#xA;expired (results in cache MISS), so we serve stale while we go to origin and&#xA;request the content (†).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;stale_if_error&lt;/code&gt;: request received, obj found in cache, but ttl has expired,&#xA;so we go to origin and the origin returns an error, so we serve stale.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† if successful, new content is cached and the TTL is updated to whatever the&#xA;cache response headers dictate.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Ultimately this means that &lt;code&gt;stale_if_error&lt;/code&gt; will only ever be initialized if&#xA;&lt;code&gt;stale_while_revalidate&lt;/code&gt; fails. Which begs the question&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why use &lt;code&gt;stale_if_error&lt;/code&gt; at all when we &lt;em&gt;could&lt;/em&gt; just set&#xA;&lt;code&gt;stale_while_revalidate&lt;/code&gt; to a large value, and it would effectively result in&#xA;the same outcome: stale content served to the user for a set period of time?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a question I don&amp;rsquo;t have an answer for, and I&amp;rsquo;ve yet to receive a&#xA;satisfactory answer to from either Fastly or the dev community.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My own opinion on this is that if my origin is unable to serve a &lt;code&gt;200 OK&lt;/code&gt;&#xA;response after 1hr of trying via &lt;code&gt;stale_while_revalidate&lt;/code&gt; then something must be&#xA;seriously wrong with my origin and so maybe that&amp;rsquo;s the appropriate indicator for&#xA;what value I should give to it in comparison to the value I would set for&#xA;&lt;code&gt;stale_if_error&lt;/code&gt; (which would be the longest value possible).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It feels like setting &lt;em&gt;both&lt;/em&gt; &lt;code&gt;stale_while_revalidate&lt;/code&gt; and &lt;code&gt;stale_if_error&lt;/code&gt; is&#xA;kind of like &amp;lsquo;cargo culting&amp;rsquo; (i.e. doing something because it&amp;rsquo;s always been done&#xA;and so people presume it&amp;rsquo;s the correct way), but at the same time I would hate&#xA;to find myself in a situation where there &lt;em&gt;was&lt;/em&gt; a subtle difference between the&#xA;two which had a very niche scenario that broke my user&amp;rsquo;s experience because I&#xA;neglected to set both stale configurations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, if these &amp;lsquo;stale&amp;rsquo; settings aren&amp;rsquo;t configured in VCL, then you&amp;rsquo;ll&#xA;need to provide them as part of Fastly&amp;rsquo;s &lt;code&gt;Surrogate-Control&lt;/code&gt; header (see&#xA;&lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial#surrogate-control&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;for the details, but be aware that VCL configured values will take precedence&#xA;over response headers from origin):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-vcl&#34;&gt;&amp;quot;Surrogate-Control&amp;quot;: &amp;quot;max-age=123, stale-while-revalidate=172800, stale-if-error=172800&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The use of &lt;code&gt;beresp.stale_if_error&lt;/code&gt; is effectively the same as Varnish&amp;rsquo;s&#xA;&lt;code&gt;beresp.grace&lt;/code&gt;. But be careful if your VCL already utilises Varnish&amp;rsquo;s original&#xA;&lt;code&gt;grace&lt;/code&gt; feature, because it will override any Fastly behaviour that is using the&#xA;&lt;code&gt;stale_if_error&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You can find more details on Fastly&amp;rsquo;s implementation&#xA;&lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/serving-stale-content&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;as well as a blog post announcing this feature&#xA;&lt;a href=&#34;https://www.fastly.com/blog/stale-while-revalidate-stale-if-error-available-today/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&#xA;If you want details on Varnish 4.0&amp;rsquo;s implementation of serving stale, see&#xA;&lt;a href=&#34;https://info.varnish-software.com/blog/grace-varnish-4-stale-while-revalidate-semantics-varnish&#34; target=&#34;_blank&#34;&gt;this&#xA;post&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;why-you-might-not-be-serving-stale&#34;&gt;Why you might not be serving stale?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You might find that you&amp;rsquo;re not serving stale even though you would expect to be.&#xA;This can be caused by a lack of&#xA;&lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/shielding&#34; target=&#34;_blank&#34;&gt;shielding&lt;/a&gt; (an&#xA;additional Fastly feature that&amp;rsquo;s designed to improve your hit ratio) as you can&#xA;only serve a stale cached object if the request ended up being routed through&#xA;the POP that has the content cached (which is more difficult without shielding&#xA;enabled).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Another reason would be to use &amp;ldquo;&lt;a href=&#34;https://docs.fastly.com/guides/purging/soft-purges&#34; target=&#34;_blank&#34;&gt;soft&#xA;purging&lt;/a&gt;&amp;rdquo; rather than hard&#xA;purges.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Lastly, there&amp;rsquo;s one quirk of Fastly&amp;rsquo;s caching implementation you might need to&#xA;know about: if you specify a &lt;code&gt;max-age&lt;/code&gt; of less than 61 minutes, then your&#xA;content will only be persisted into memory (and there are many situations where&#xA;a cached object in memory can be removed). To make sure the object is persisted&#xA;(i.e. cached) on disk and thus available for a longer period of time for serving&#xA;stale, you must set a &lt;code&gt;max-age&lt;/code&gt; above 61 minutes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth reading &lt;a href=&#34;https://docs.fastly.com/guides/performance-tuning/serving-stale-content#why-serving-stale-content-may-not-work-as-expected&#34; target=&#34;_blank&#34;&gt;fastly&amp;rsquo;s notes on why you might not be serving&#xA;stale&lt;/a&gt;&#xA;which additionally includes notes on things like the fact that their&#xA;implementation is an LRU (Least Recently Used) cache, and so even if a cached&#xA;object&amp;rsquo;s TTL has not expired it might be so infrequently requested/accessed that&#xA;it&amp;rsquo;ll be evicted from the cache any way! The LRU affects both fresh (i.e.&#xA;non-expired) objects &lt;em&gt;and&lt;/em&gt; &amp;lsquo;stale&amp;rsquo; objects (i.e. TTL has expired but they have&#xA;stale config values that haven&amp;rsquo;t expired).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;stale-for-client-devices&#34;&gt;Stale for Client Devices&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth reiterating a segment of the earlier &lt;a href=&#34;#caching-priority-list&#34;&gt;caching priority&#xA;list&lt;/a&gt; which is that &lt;code&gt;Cache-Control&lt;/code&gt; &lt;em&gt;can&lt;/em&gt; include&#xA;serving stale directives such as &lt;code&gt;stale-while-revalidate&lt;/code&gt; and &lt;code&gt;stale-if-error&lt;/code&gt;,&#xA;but they are typically utilized with &lt;code&gt;Surrogate-Control&lt;/code&gt; more than they are with&#xA;&lt;code&gt;Cache-Control&lt;/code&gt;. If Fastly receives no &lt;code&gt;Surrogate-Control&lt;/code&gt; but it does get&#xA;&lt;code&gt;Cache-Control&lt;/code&gt; with those directives it &lt;em&gt;will&lt;/em&gt; presume those are defined for&#xA;its benefit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Client devices (e.g. web browsers) can respect those stale directives, but it&amp;rsquo;s&#xA;not very well supported currently (see &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Browser_compatibility&#34; target=&#34;_blank&#34;&gt;MDN compatibility&#xA;table&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;different-actions-for-different-states&#34;&gt;Different actions for different states&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So if we find a stale object, we need to deliver it to the user. But the action&#xA;you take (as far as Fastly&amp;rsquo;s implementation of Varnish is concerned) depends on&#xA;which state Varnish currently is in (&lt;code&gt;vcl_fetch&lt;/code&gt; or &lt;code&gt;vcl_deliver&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you&amp;rsquo;re in &lt;code&gt;vcl_fetch&lt;/code&gt; you&amp;rsquo;ll &lt;code&gt;return(deliver_stale)&lt;/code&gt; and in &lt;code&gt;vcl_deliver&lt;/code&gt;&#xA;you&amp;rsquo;ll &lt;code&gt;return(restart)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;why-the-difference&#34;&gt;Why the difference?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;The reason for this difference is to do with Fastly&amp;rsquo;s Varnish implementation and&#xA;how they handle &amp;lsquo;clustering&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;According to Fastly you&amp;rsquo;ll typically find, due to the way their &amp;lsquo;clustering&amp;rsquo;&#xA;works, that &lt;code&gt;vcl_fetch&lt;/code&gt; and &lt;code&gt;vcl_deliver&lt;/code&gt; generally run on &lt;em&gt;different&lt;/em&gt; servers&#xA;(although that&amp;rsquo;s not always the case, as we&amp;rsquo;ll soon see) and so different&#xA;servers will have different caches.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;What we refer to as &amp;lsquo;clustering&amp;rsquo; is when two servers within the same POP&#xA;communicate with each other for cache optimization purposes&amp;rdquo; &amp;ndash; Fastly&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h4 id=&#34;the-happy-path-stale-found-in-vcl-fetch&#34;&gt;The happy path (stale found in &lt;code&gt;vcl_fetch&lt;/code&gt;)&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;If a stale object is found in &lt;code&gt;vcl_fetch&lt;/code&gt;, then &lt;code&gt;deliver_stale&lt;/code&gt; will send the&#xA;found stale content to &lt;code&gt;vcl_deliver&lt;/code&gt; with a status of 200. This means when&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; checks the status code it&amp;rsquo;ll not see a 5xx and so it&amp;rsquo;ll just&#xA;deliver that stale content to the user.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;the-longer-path-stale-found-in-vcl-deliver&#34;&gt;The longer path (stale found in &lt;code&gt;vcl_deliver&lt;/code&gt;)&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Imagine &lt;code&gt;vcl_fetch&lt;/code&gt; is running on server &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;vcl_deliver&lt;/code&gt; is running on&#xA;server &lt;code&gt;B&lt;/code&gt; (due to Fastly&amp;rsquo;s &amp;lsquo;clustering&amp;rsquo; infrastructure) and you looked for a&#xA;stale object in &lt;code&gt;vcl_fetch&lt;/code&gt;. The stale object might not exist there and so you&#xA;would end up passing whatever the origin&amp;rsquo;s 5xx response was onto &lt;code&gt;vcl_deliver&lt;/code&gt;&#xA;running on server &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now in &lt;code&gt;vcl_deliver&lt;/code&gt; we check &lt;code&gt;stale.exists&lt;/code&gt; and it might tell us that an object&#xA;&lt;em&gt;was&lt;/em&gt; found, remember: this is a different server with a different cache.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this scenario we have a 5xx object that we&amp;rsquo;re about to deliver to the client,&#xA;but on this particular server (&lt;code&gt;B&lt;/code&gt;) we&amp;rsquo;ve since discovered there is actually a&#xA;stale object we can serve to the user instead. So how do we now give the user&#xA;this stale object and not the 5xx content that came from origin?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to do that, we need to restart the request cycle. When we&#xA;&lt;code&gt;return(restart)&lt;/code&gt; in &lt;code&gt;vcl_deliver&lt;/code&gt; it forces Fastly&amp;rsquo;s version of Varnish to&#xA;break its clustering behaviour and to now route the request completely through&#xA;whatever server &lt;code&gt;vcl_deliver&lt;/code&gt; is currently running on (in this example it&amp;rsquo;ll&#xA;ensure the entire request flow will go through server &lt;code&gt;B&lt;/code&gt; - which we know has a&#xA;stale object available).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means we end up processing the request again, but this time when we make a&#xA;request to origin and get a 5xx back, we will (in &lt;code&gt;vcl_fetch&lt;/code&gt;) end up finding&#xA;the stale object (remember: our earlier restart has forced clustering behaviour&#xA;to be broken so we&amp;rsquo;re routing through the same server &lt;code&gt;B&lt;/code&gt;). Now we find&#xA;&lt;code&gt;stale.exists&lt;/code&gt; has matched in &lt;code&gt;vcl_fetch&lt;/code&gt; we will &lt;code&gt;return(deliver_stale)&lt;/code&gt; (which&#xA;we failed to do previously due to the stale object not existing on server &lt;code&gt;A&lt;/code&gt;)&#xA;and this means the stale content with a status of 200 is passed to &lt;code&gt;vcl_deliver&lt;/code&gt;&#xA;and that will subsequently deliver the stale object to the client.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;the-unhappy-path-stale-not-found-anywhere&#34;&gt;The unhappy path (stale not found anywhere)&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;In this scenario we don&amp;rsquo;t find a stale object in either &lt;code&gt;vcl_fetch&lt;/code&gt; or&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; and so we end up serving the 5xx content that we got from origin&#xA;to the client. Although you may want to attempt to restart the request and use a&#xA;custom header (e.g. &lt;code&gt;set req.http.X-Serve-500-Page = &amp;quot;true&amp;quot;&lt;/code&gt;) in order to&#xA;indicate to &lt;code&gt;vcl_recv&lt;/code&gt; that you want to short-circuit the request cycle and&#xA;serve a custom error page instead.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;test-serving-stale&#34;&gt;Test Serving Stale&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to test that you&amp;rsquo;re serving stale content you&amp;rsquo;ll need to:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;ensure that you are able to force a resource to succeed &lt;em&gt;and&lt;/em&gt; fail when necessary.&lt;/li&gt;&#xA;&lt;li&gt;ensure that you have &lt;code&gt;max-age&lt;/code&gt;, &lt;code&gt;stale-while-revalidate&lt;/code&gt; and &lt;code&gt;stale-if-error&lt;/code&gt; set to short values.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;For point 1. we need this because the serving of stale content during&#xA;&lt;code&gt;stale-if-error&lt;/code&gt; will only happen if the backend/origin server fails or returns&#xA;an error status. But if you&amp;rsquo;re testing a real backend/origin server then you&#xA;&lt;em&gt;want&lt;/em&gt; it to be running 😅 so being able to force it to look like it failed is&#xA;ideal for testing our &amp;lsquo;serve stale&amp;rsquo; VCL code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For point 2. we need this because the serving of stale content will only happen&#xA;when the TTL of the cached resource has expired. If we didn&amp;rsquo;t do this, then we&#xA;would have to wait for whatever TTL was set by the backend/origin server to&#xA;expire (which could be a very long time!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll serve stale content for a period of time while we try and acquire fresher&#xA;content (e.g. &lt;code&gt;stale-while-revalidate&lt;/code&gt;), followed by serving stale for a period&#xA;of time if the backend/origin server fails to respond after the revalidation&#xA;period (e.g. &lt;code&gt;stale-if-error&lt;/code&gt;). So again, if either of those stale directives&#xA;have long TTLs set by the backend/origin server, then it&amp;rsquo;ll make testing our&#xA;ability to serve stale impractical.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to achieve these two requirements, I&amp;rsquo;ve found the following approach to&#xA;work quite well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First, add the following code to your &lt;code&gt;vcl_fetch&lt;/code&gt; subroutine&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.http.X-TTLs == &amp;quot;shorten&amp;quot;) { &#xA;  set beresp.ttl = 10s;&#xA;  set beresp.stale_while_revalidate = 20s;&#xA;  set beresp.stale_if_error = 60s;&#xA;&#xA;  unset beresp.http.ETag;&#xA;  unset beresp.http.Last-Modified;&#xA;}&#xA;&#xA;if (req.http.X-ResponseState == &amp;quot;fail&amp;quot;) {&#xA;  set beresp.status = 500;&#xA;  set beresp.cacheable = false;&#xA;}&#xA;&#xA;if (beresp.status &amp;gt;= 500 &amp;amp;&amp;amp; beresp.status &amp;lt; 600) {&#xA;  if (stale.exists) {&#xA;    return(deliver_stale);&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you should already have the code that checks for &lt;code&gt;stale.exists&lt;/code&gt; etc, but&#xA;I&amp;rsquo;m including it for the sake of clarity.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;mistake-1&#34;&gt;Mistake 1.&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Now the mistake I initially made was instead of setting &lt;code&gt;beresp.ttl&lt;/code&gt;,&#xA;&lt;code&gt;beresp.stale_while_revalidate&lt;/code&gt;, &lt;code&gt;beresp.stale_if_error&lt;/code&gt; (as shown above) I&#xA;tried to manipulate &lt;code&gt;beresp.http.Surrogate-Control&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set beresp.http.Surrogate-Control = &amp;quot;max-age=10, stale-while-revalidate=20, stale-if-error=60&amp;quot;;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason that doesn&amp;rsquo;t work is that it would only affect &lt;em&gt;downstream&lt;/em&gt; caches&#xA;(inc. a Fastly cache if this cache node was a &amp;lsquo;&lt;a href=&#34;#shielding&#34;&gt;shield&lt;/a&gt;&amp;rsquo; node). This&#xA;is because the &lt;code&gt;Surrogate-Control&lt;/code&gt; and &lt;code&gt;Cache-Control&lt;/code&gt; headers are &lt;em&gt;parsed&lt;/em&gt;&#xA;before &lt;code&gt;vcl_fetch&lt;/code&gt; is called.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if we want to affect the duration for which Fastly caches an object (inc.&#xA;stale TTLs) we need to manipulate the &lt;code&gt;beresp.ttl&lt;/code&gt;,&#xA;&lt;code&gt;beresp.stale_while_revalidate&lt;/code&gt;, &lt;code&gt;beresp.stale_if_error&lt;/code&gt; variables.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With the above VCL in place we can make a request with the &lt;code&gt;X-TTLs&lt;/code&gt; header set&#xA;with a value of &lt;code&gt;shorten&lt;/code&gt; to cause the cached object to have a shorter set of&#xA;caching TTLs than the origin intended.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then we can wait for the &lt;code&gt;max-age&lt;/code&gt; TTL to expire before making the same request&#xA;again and see that now Fastly will attempt to revalidate the content and so&#xA;during its &lt;code&gt;stale-while-revalidate&lt;/code&gt; time period Fastly will serve stale content&#xA;back to us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then we can wait for the &lt;code&gt;stale-while-revalidate&lt;/code&gt; TTL to expire before making&#xA;the same request again but changing &lt;code&gt;X-TTLs&lt;/code&gt; to &lt;code&gt;X-ResponseState&lt;/code&gt; and setting&#xA;the value to &lt;code&gt;fail&lt;/code&gt;, which means when Fastly attempts to acquire the content&#xA;from the origin it&amp;rsquo;ll think it received an error from the backend/origin server&#xA;and go ahead and serve stale content back to us.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;mistake-2&#34;&gt;Mistake 2.&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Another thing I had initially done wrong was not handle the situation where the&#xA;origin would serve back a &lt;code&gt;304 Not Modified&lt;/code&gt;. In this scenario Varnish will not&#xA;execute &lt;code&gt;vcl_fetch&lt;/code&gt; (why would it? there&amp;rsquo;s no change in the content, based upon&#xA;its &amp;lsquo;conditional request&amp;rsquo; it made and so no FULL request needs to be made to the&#xA;origin to fetch the full response).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this causes an issue is because along with a &lt;code&gt;304&lt;/code&gt; not executing&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt; (and thus our cache directives and failure modifications wont be&#xA;actioned) it means the object in the cache will be updated in a way that can&#xA;break our expectations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically, when Varnish receives a &lt;code&gt;304&lt;/code&gt; from origin, it will re-cache the&#xA;object with the &lt;em&gt;original&lt;/em&gt; TTLs (normally this would be fine as this would be&#xA;our &lt;em&gt;modified&lt;/em&gt; cache directives) but it&amp;rsquo;ll only do that if there is no valid&#xA;&lt;code&gt;Cache-Control&lt;/code&gt; or &lt;code&gt;Surrogate-Control&lt;/code&gt; header found in the &lt;code&gt;304&lt;/code&gt; response from&#xA;origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in my case, our origin responded with a &lt;code&gt;304&lt;/code&gt; and also provided the&#xA;&lt;em&gt;original&lt;/em&gt; (i.e. unmodified) &lt;code&gt;Surrogate-Control&lt;/code&gt; header, and thus those TTLs&#xA;were being applied to the re-cached object. Making my testing code&amp;rsquo;s assertions&#xA;about the state of the object incorrect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This had me confused for a &lt;em&gt;long&lt;/em&gt; time. With the help of Fastly support we&#xA;realized the best way to avoid this &lt;code&gt;304&lt;/code&gt; response from messing up our&#xA;expectations was to cause strip the &lt;code&gt;ETag&lt;/code&gt; and &lt;code&gt;Last-Modified&lt;/code&gt; headers from the&#xA;first &lt;code&gt;200 OK&lt;/code&gt; response we got back from the origin.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we do this is so that the Varnish cache has no way of making a&#xA;conditional request when it comes to us testing &lt;code&gt;stale-while-revalidate&lt;/code&gt; and so&#xA;it is forced to make a full request to the origin, where upon Varnish will have&#xA;to execute &lt;code&gt;vcl_fetch&lt;/code&gt; and our code modifications will again be applied.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we didn&amp;rsquo;t do that, then there would literally be &lt;em&gt;no way&lt;/em&gt; of testing our&#xA;website&amp;rsquo;s ability to serve stale unless we changed the backend to a different&#xA;origin server that was pre-configured to respond how we needed it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Having a different backend was something we had already done in the past and&#xA;helped us to validate our VCL code and cache headers were correct, but it didn&amp;rsquo;t&#xA;tell us if our &lt;em&gt;real&lt;/em&gt; pages would serve stale at the critical time that we&#xA;needed them to &amp;ndash; so that&amp;rsquo;s way we wanted to control everything from VCL rather&#xA;than using a special backend.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://gist.github.com/Integralist/f7a6abdd946ad5b3b06907069f79cc48&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;is an example Python3 script that demonstrates how we verify these behaviours.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;disable-caching&#34;&gt;Disable Caching&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s possible to disable caching for either the client or fastly, or both! But&#xA;it gets confusing with all the various documentation pages fastly provides to&#xA;know which one is the source of truth (useful information is spread across all&#xA;of them).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In my experience I&amp;rsquo;ve found the following to be sufficient&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;any time you want Fastly to cache your content use &lt;code&gt;Surrogate-Control&lt;/code&gt;,&#xA;and this will take precedence over &lt;code&gt;Cache-Control&lt;/code&gt; &lt;em&gt;EXCEPT&lt;/em&gt; when&#xA;&lt;code&gt;Cache-Control&lt;/code&gt; has the value &lt;code&gt;private&lt;/code&gt; included somewhere inside it. So&#xA;generally if I&amp;rsquo;m doing that I&amp;rsquo;ll just make sure I&amp;rsquo;m not sending a&#xA;&lt;code&gt;Surrogate-Control&lt;/code&gt; as it&amp;rsquo;ll just be confusing for anyone reading that code.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Disable Client Caching: &lt;code&gt;Cache-Control: no-store, must-revalidate&lt;/code&gt; (&lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial#applying-different-cache-rules-for-fastly-and-browsers&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Disable CDN Caching: &lt;code&gt;Cache-Control: private&lt;/code&gt; (&lt;a href=&#34;https://docs.fastly.com/guides/tutorials/cache-control-tutorial#do-not-cache&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Disable ALL Caching: &lt;code&gt;Cache-Control: no-cache, no-store, private, must-revalidate, max-age=0, max-stale=0, post-check=0, pre-check=0&lt;/code&gt; + &lt;code&gt;Pragma: no-cache&lt;/code&gt; + &lt;code&gt;Expires: 0&lt;/code&gt; (&lt;a href=&#34;https://docs.fastly.com/guides/debugging/temporarily-disabling-caching&#34; target=&#34;_blank&#34;&gt;docs&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;logging&#34;&gt;Logging&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With Fastly, to set-up logging you&amp;rsquo;ll need to use their UI, as this means they&#xA;can configure the relevant integration with your log aggregation provider. This&#xA;is fairly straight forward and obvious but what people &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; realise is that&#xA;by default Fastly will generate a subroutine called &lt;code&gt;vcl_log&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, as part of the log configuration in the Fastly UI you must specify a &amp;ldquo;log&#xA;format&amp;rdquo; (think an Apache web server log format syntax). If you don&amp;rsquo;t set a value&#xA;for the log format (e.g. it&amp;rsquo;s an empty field) then the VCL will have a &lt;code&gt;vcl_log&lt;/code&gt;&#xA;subroutine that looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_log {&#xA;#--FASTLY LOG START&#xA;  # default response conditions&#xA;  log {&amp;quot;syslog &amp;lt;service_id&amp;gt; &amp;lt;service_name&amp;gt; :: &amp;quot;} ;&#xA;#--FASTLY LOG END&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Effectively it&amp;rsquo;s an empty log message :-/&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you &lt;em&gt;do&lt;/em&gt; provide a log format value, then it &lt;em&gt;could&lt;/em&gt; look something like the&#xA;following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_log {&#xA;#--FASTLY LOG START&#xA;  # default response conditions&#xA;  log {&amp;quot;syslog &amp;lt;service_id&amp;gt; &amp;lt;service_name&amp;gt; :: &amp;quot;} &#xA;  req.http.Fastly-Client-IP &amp;quot; [&amp;quot; strftime({&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;}, time.start) &amp;quot;.&amp;quot; &#xA;  time.start.msec_frac {&amp;quot;] &amp;quot;&amp;quot;} cstr_escape(req.request) &amp;quot; &amp;quot; cstr_escape(req.url)&#xA;  &amp;quot; &amp;quot; cstr_escape(req.proto) {&amp;quot;&amp;quot; &amp;quot;} resp.status &amp;quot; &amp;quot; resp.body_bytes_written &amp;quot; &amp;quot;&#xA;  tls.client.protocol &amp;quot; &amp;quot; fastly_info.state &amp;quot; &amp;quot; req.http.user-agent;&#xA;#--FASTLY LOG END&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so another important thing to think about is that the &lt;code&gt;vcl_log&lt;/code&gt; subroutine&#xA;executes &lt;em&gt;after&lt;/em&gt; &lt;code&gt;vcl_deliver&lt;/code&gt;. So it&amp;rsquo;s the &lt;em&gt;very last&lt;/em&gt; routine to be executed&#xA;before Varnish completes the request (so this is even after it has delivered the&#xA;response to the client).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this subroutine exists is because logging inside of &lt;code&gt;vcl_deliver&lt;/code&gt;&#xA;(which is how Fastly &lt;em&gt;used&lt;/em&gt; to work, i.e. they would auto-generate the log call&#xA;inside of &lt;code&gt;vcl_deliver&lt;/code&gt;) Fastly wouldn&amp;rsquo;t have certain response variables&#xA;available, such as determining how long it took to send the first byte of the&#xA;response to the client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What confused &lt;em&gt;me&lt;/em&gt; about the logging set-up was the fact that I didn&amp;rsquo;t realise I&#xA;was looking at things too much from an &amp;lsquo;engineering&amp;rsquo; perspective. By that I&#xA;mean, not all of the UI features Fastly provides exist just for my benefit :-)&#xA;and I should probably elaborate on what I mean by that&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what I was confusedly thinking was: &amp;ldquo;why is Fastly generating only a &lt;em&gt;single&lt;/em&gt;&#xA;log call in &lt;code&gt;vcl_log&lt;/code&gt;, is there a technical reason for that or a limitation with&#xA;Varnish? I want to make multiple log calls throughout my request/response flow,&#xA;I don&amp;rsquo;t want just a single log at the end as that&amp;rsquo;s not very useful to me!&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well it ended up simply just being that some Fastly users don&amp;rsquo;t want to write&#xA;their own VCL (or don&amp;rsquo;t know anything about writing code) and so they are quite&#xA;happy with knowing that the UI will trigger a single log call at the end of each&#xA;request cycle.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where (as a programmer) I was expecting to add log calls all over the place!&#xA;Turns our this was possible of course, but I also never realised a &lt;code&gt;vcl_log&lt;/code&gt;&#xA;subroutine existed nor that it was being &lt;em&gt;auto-generated&lt;/em&gt; for me by Fastly once&#xA;I had configured my logging endpoint in their UI.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This meant I also never realised that an &lt;em&gt;extra&lt;/em&gt; log call (after all the log&#xA;calls I was manually adding to my custom VCL) was being executed!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So when I eventually stumbled across a Fastly documentation page talking about&#xA;&amp;ldquo;duplicate logs&amp;rdquo;, I started digging deeper into why that might be &amp;hellip;and that&amp;rsquo;s&#xA;where I discovered &lt;code&gt;vcl_log&lt;/code&gt; was a thing and I needed to read up on it and how&#xA;it worked and why it existed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, the documentation then goes on to mention using the UI to create a custom&#xA;&amp;lsquo;condition&amp;rsquo; to prevent Fastly&amp;rsquo;s auto-generated log from being executed. This&#xA;intrigued me. I was thinking &amp;ldquo;what is this magical &amp;lsquo;condition feature&amp;rsquo; they&#xA;have?&amp;rdquo;. Well, turns out that I was again thinking too much like an engineer and&#xA;not enough like a normal Joe Bloggs user who knows nothing about programming, as&#xA;this &amp;lsquo;feature&amp;rsquo; just generates a standard conditional &amp;lsquo;if statement&amp;rsquo; code block&#xA;around the auto-generated log call, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_log {&#xA;#--FASTLY LOG START&#xA;  # default response conditions&#xA;  # Response Condition: generate-a-log Prio: 10&#xA;  if( !req.url ) {&#xA;    log {&amp;quot;syslog &amp;lt;service_id&amp;gt; &amp;lt;service_name&amp;gt; :: &amp;quot;} ;&#xA;  }&#xA;#--FASTLY LOG END&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can probably tell, this recommended condition will never match and so the&#xA;final log call isn&amp;rsquo;t executed, thus avoiding an unneccessary duplicate log call.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Mystery solved.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/sherlock.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/sherlock.webp&#34; alt=&#34;sherlock&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;filtering-and-sampling-logs&#34;&gt;Filtering and Sampling Logs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I want to also mention that logging can be expensive if you&amp;rsquo;re sending &lt;em&gt;ALL&lt;/em&gt;&#xA;your Fastly traffic logs to a log aggregation/analysis service (such as&#xA;&lt;a href=&#34;https://www.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt;), and so two things we did to help combat&#xA;this problem was&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;only send &amp;lsquo;uncacheable request&amp;rsquo; logs&lt;/li&gt;&#xA;&lt;li&gt;only send a sample of our logs&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The following VCL snippet demonstrates how to do this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;vcl_log {&#xA;  ...&#xA;&#xA;  // 75% of uncacheable logs will be sampled&#xA;  if (fastly_info.state ~ &amp;quot;^(MISS|PASS)&amp;quot; &amp;amp;&amp;amp; randombool(3,4)) {&#xA;    log ...;&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;logging-memory-exhaustion&#34;&gt;Logging Memory Exhaustion&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We discovered an issue with our logging code which meant we would see &lt;code&gt;(null)&lt;/code&gt;&#xA;log lines being generated. The cause of this turned out to be the Fastly&#xA;&amp;lsquo;workspace&amp;rsquo; (as they refer to it) would run out of memory while generating our&#xA;log output that they would stream to either GCS or AWS S3.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You can inspect the workspace using the undocumented &lt;code&gt;workspace.bytes_free&lt;/code&gt;&#xA;property, and this value will change as you make modifications to your&#xA;request/response and other related objects.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;workspace&amp;rsquo; is the amount of memory allocated to &lt;em&gt;each&lt;/em&gt; in-flight request,&#xA;and its value is set to 128k. So although the JSON object we&amp;rsquo;re building is&#xA;small, &lt;em&gt;prior&lt;/em&gt; to that, our request flow might be making lots of HTTP header&#xA;modifications and all those things are counting towards the overall memory being&#xA;consumed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So ultimately be wary of making too many HTTP modifcations as you might discover&#xA;you&amp;rsquo;ll end up losing log data.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;json-structured-logging&#34;&gt;JSON Structured Logging&lt;/h4&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see the &lt;a href=&#34;#update-20200914&#34;&gt;update&lt;/a&gt; for a way to use &amp;lsquo;long strings&amp;rsquo; to&#xA;construct easier to read JSON logs.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Generating JSON structured output is not easy in VCL. The below VCL snippet&#xA;demonstrates the &amp;lsquo;manual&amp;rsquo; approach (encoding &lt;code&gt;&amp;quot;&lt;/code&gt; as &lt;code&gt;%22&lt;/code&gt; and concatenating&#xA;across multiple lines). This was the best solution for us as the alternatives&#xA;were unsuitable:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/fastly/vcl-json-generate&#34; target=&#34;_blank&#34;&gt;github.com/fastly/vcl-json-generate&lt;/a&gt;&#xA;is wildly verbose in comparison, although it&amp;rsquo;s supposed to make things&#xA;easier?&lt;/li&gt;&#xA;&lt;li&gt;using a &amp;ldquo;long string&amp;rdquo; to avoid encoding nested double quote, but then&#xA;everything must be all on &lt;em&gt;one&lt;/em&gt; line!?, e.g. &lt;code&gt;{&amp;quot;{  &amp;quot;foo&amp;quot;:&amp;quot;&amp;quot;} req.http.X-Foo {&amp;quot;&amp;quot;,  &amp;quot;bar&amp;quot;:&amp;quot;} req.http.X-Bar {&amp;quot; }&amp;quot;};&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we have two seperate services, one production and one staging and we run&#xA;the same VCL code in both. This requires us to have logic that checks whether&#xA;our code is running in the stage environment or not (see below for example).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;declare local var.stage_service_id STRING;&#xA;declare local var.prod_service_id STRING;&#xA;declare local var.running_service_id STRING;&#xA;&#xA;set var.stage_service_id = req.http.X-Fastly-ServiceID-Stage;&#xA;set var.prod_service_id = req.http.X-Fastly-ServiceID-Prod;&#xA;set var.running_service_id = var.stage_service_id;&#xA;&#xA;if (req.service_id == var.prod_service_id) {&#xA;  set var.running_service_id = var.prod_service_id;&#xA;}&#xA;&#xA;declare local var.json STRING;&#xA;&#xA;set var.json = &amp;quot;{&amp;quot; +&#xA;  &amp;quot;%22http%22: {&amp;quot; +&#xA;    &amp;quot;%22body_size%22: %22&amp;quot; + resp.body_bytes_written + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22content_type%22: %22&amp;quot; + resp.http.Content-Type + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22host%22: %22&amp;quot; + req.http.host + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22method%22: %22&amp;quot; + req.method + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22path%22: %22&amp;quot; + json.escape(req.url) + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22protocol%22: %22&amp;quot; + req.proto + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22request_time%22: &amp;quot; + time.to_first_byte + &amp;quot;,&amp;quot; +&#xA;    &amp;quot;%22served_stale%22: &amp;quot; + req.http.X-BF-Served-Stale + &amp;quot;,&amp;quot; +&#xA;    &amp;quot;%22status_code%22: &amp;quot; + resp.status + &amp;quot;,&amp;quot; +&#xA;    &amp;quot;%22tls_version%22: %22&amp;quot; + tls.client.protocol + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22uri%22: %22&amp;quot; + json.escape(if(req.http.Fastly-SSL, &amp;quot;https&amp;quot;, &amp;quot;http&amp;quot;)&#xA;    + &amp;quot;://&amp;quot; + req.http.host + req.url) + &amp;quot;%22,&amp;quot; +&#xA;    &amp;quot;%22user_agent%22: %22&amp;quot; + json.escape(req.http.User-Agent) + &amp;quot;%22&amp;quot; +&#xA;  &amp;quot;},&amp;quot; +&#xA;  &amp;quot;%22network%22: {&amp;quot; +&#xA;    &amp;quot;%22client%22: {&amp;quot; +&#xA;      &amp;quot;%22ip%22: %22&amp;quot; + req.http.Fastly-Client-IP + &amp;quot;%22&amp;quot; +&#xA;    &amp;quot;},&amp;quot; +&#xA;    &amp;quot;%22server%22: {&amp;quot; +&#xA;      &amp;quot;%22state%22: %22&amp;quot; + fastly_info.state + &amp;quot;%22&amp;quot; +&#xA;    &amp;quot;}&amp;quot; +&#xA;  &amp;quot;},&amp;quot; +&#xA;  &amp;quot;%22timestamp%22: &amp;quot; + time.start.msec + &amp;quot;,&amp;quot; +&#xA;  &amp;quot;%22timestamp_sec%22: &amp;quot; + time.start.sec + &amp;quot;,&amp;quot; + # exists to support BigQuery&#xA;  &amp;quot;%22upstreams%22: {&amp;quot; +&#xA;    &amp;quot;%22service%22: %22&amp;quot; + req.http.X-BF-Backend + &amp;quot;%22&amp;quot; +&#xA;  &amp;quot;}&amp;quot;&#xA;&amp;quot;}&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There was a way to combine long strings (&lt;code&gt;{&amp;quot;...&amp;quot;}&lt;/code&gt;, e.g. to use double quote&#xA;inside of a string:&lt;code&gt;{&amp;quot;&amp;quot;&amp;quot;}&lt;/code&gt;) over multiple lines (demonstrated below) but I&amp;rsquo;d&#xA;argue it&amp;rsquo;s still not as readable as you might imagine, and missing just one&#xA;opening or closing bracket will cause you nothing but pain and heartache:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;declare local var.json STRING;&#xA;&#xA;set var.json = &amp;quot;{&amp;quot; +&#xA;  {&amp;quot;&amp;quot;http&amp;quot;: {&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;body_size&amp;quot;: &amp;quot;&amp;quot;} + resp.body_bytes_written + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;content_type&amp;quot;: &amp;quot;&amp;quot;} + resp.http.Content-Type + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;host&amp;quot;: &amp;quot;&amp;quot;} + req.http.host + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;method&amp;quot;: &amp;quot;&amp;quot;} + req.method + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;path&amp;quot;: &amp;quot;&amp;quot;} + json.escape(req.url) + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;protocol&amp;quot;: &amp;quot;&amp;quot;} + req.proto + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;request_time&amp;quot;: &amp;quot;} + time.to_first_byte + &amp;quot;,&amp;quot; +&#xA;    {&amp;quot;&amp;quot;status_code&amp;quot;: &amp;quot;} + resp.status + &amp;quot;,&amp;quot; +&#xA;    {&amp;quot;&amp;quot;tls_version&amp;quot;: &amp;quot;&amp;quot;} + tls.client.protocol + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;uri&amp;quot;: &amp;quot;&amp;quot;} + json.escape(if(req.http.Fastly-SSL, &amp;quot;https&amp;quot;, &amp;quot;http&amp;quot;) &#xA;    + &amp;quot;://&amp;quot; + req.http.host + req.url) + {&amp;quot;&amp;quot;,&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;user_agent&amp;quot;: &amp;quot;&amp;quot;} + json.escape(req.http.User-Agent) + {&amp;quot;&amp;quot;&amp;quot;} +&#xA;  &amp;quot;},&amp;quot; +&#xA;  {&amp;quot;&amp;quot;network&amp;quot;: {&amp;quot;} +&#xA;    {&amp;quot;&amp;quot;client&amp;quot;: {&amp;quot;} +&#xA;      {&amp;quot;&amp;quot;ip&amp;quot;: &amp;quot;&amp;quot;} + req.http.Fastly-Client-IP + {&amp;quot;&amp;quot;&amp;quot;} +&#xA;    &amp;quot;},&amp;quot; +&#xA;    {&amp;quot;&amp;quot;server&amp;quot;: {&amp;quot;} +&#xA;      {&amp;quot;&amp;quot;state&amp;quot;: &amp;quot;&amp;quot;} + fastly_info.state + {&amp;quot;&amp;quot;&amp;quot;} +&#xA;    &amp;quot;}&amp;quot; +&#xA;  &amp;quot;},&amp;quot; +&#xA;  {&amp;quot;&amp;quot;timestamp&amp;quot;: &amp;quot;} + time.start.msec + &amp;quot;,&amp;quot; +&#xA;  {&amp;quot;&amp;quot;timestamp_sec&amp;quot;: &amp;quot;} + time.start.sec + # exists to support BigQuery&#xA;&amp;quot;}&amp;quot;;&#xA;&#xA;log var.json;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So manually constructing the JSON was what we opted for, and once you get used&#xA;to the endless &lt;code&gt;%22&lt;/code&gt; it&amp;rsquo;s actually quite readable IMHO (when compared to the&#xA;alternatives we just described).&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;fixing-the-memory-issue&#34;&gt;Fixing the Memory Issue&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Now here&amp;rsquo;s how we worked-around the memory issue causing a &lt;code&gt;(null)&lt;/code&gt; log line:&#xA;before we trigger our &lt;code&gt;log&lt;/code&gt; call we first check that Fastly&amp;rsquo;s workspace hasn&amp;rsquo;t&#xA;been exhausted (the variable contains the error code raised by the last&#xA;function). If we find an &amp;lsquo;out of memory&amp;rsquo; error, then we won&amp;rsquo;t attempt to call&#xA;the &lt;code&gt;log&lt;/code&gt; function (as that would result in the &lt;code&gt;(null)&lt;/code&gt; for a log line).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation:&#xA;&lt;a href=&#34;https://docs.fastly.com/vcl/variables/fastly-error/&#34; target=&#34;_blank&#34;&gt;docs.fastly.com/vcl/variables/fastly-error/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to reiterate that this isn&amp;rsquo;t a &lt;em&gt;solution&lt;/em&gt;, but a &lt;em&gt;work-around&lt;/em&gt;.&#xA;We don&amp;rsquo;t know how many logs we&amp;rsquo;re losing due to memory exhaustion (it could be&#xA;lots!) so this is a problem we need to investigate further (as of October 2019,&#xA;&amp;hellip;wow did I really start writing this post two years ago!!? time flies heh).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (fastly.error != &amp;quot;ESESOOM&amp;quot;) {&#xA;  log &amp;quot;syslog &amp;quot; var.running_service_id &amp;quot; logs_to_s3 :: &amp;quot; var.json;&#xA;  log &amp;quot;syslog &amp;quot; var.running_service_id &amp;quot; logs_to_gcs :: &amp;quot; var.json;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;logs_to_s3&lt;/code&gt; and &lt;code&gt;logs_to_gcs&lt;/code&gt; are references to the two different log&#xA;streams we setup within the Fastly UI.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;update-2020-09-14&#34;&gt;Update 2020.09.14&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Whilst reading through a fastly blog post on NEL &amp;ldquo;Network Error Logging&amp;rdquo; I&#xA;noticed the secret sauce that makes using long strings for JSON formatting&#xA;actually work! You have to remove the line breaks introduced by the long strings&#xA;🤦🏼‍♂️&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set var.json = regsuball(var.json, {&amp;quot;\s(?=([^&amp;quot;]*\&amp;quot;[^&amp;quot;]*&amp;quot;)*[^&amp;quot;]*$)&amp;quot;},&amp;quot;&amp;quot;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the full example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;declare local var.json STRING;&#xA;&#xA;set var.json = {&amp;quot;{&#xA;  &amp;quot;http&amp;quot;: {&#xA;    &amp;quot;body_size&amp;quot;: &amp;quot;&amp;quot;} resp.body_bytes_written {&amp;quot;&amp;quot;,&#xA;    &amp;quot;content_type&amp;quot;: &amp;quot;&amp;quot;} resp.http.Content-Type {&amp;quot;&amp;quot;,&#xA;    &amp;quot;host&amp;quot;: &amp;quot;&amp;quot;} req.http.host {&amp;quot;&amp;quot;,&#xA;    &amp;quot;method&amp;quot;: &amp;quot;&amp;quot;} req.method {&amp;quot;&amp;quot;,&#xA;    &amp;quot;path&amp;quot;: &amp;quot;&amp;quot;} json.escape(req.url) {&amp;quot;&amp;quot;,&#xA;    &amp;quot;protocol&amp;quot;: &amp;quot;&amp;quot;} req.proto {&amp;quot;&amp;quot;,&#xA;    &amp;quot;request_time&amp;quot;: &amp;quot;} time.to_first_byte {&amp;quot;,&#xA;    &amp;quot;status_code&amp;quot;: &amp;quot;} resp.status {&amp;quot;,&#xA;    &amp;quot;tls_version&amp;quot;: &amp;quot;&amp;quot;} tls.client.protocol {&amp;quot;&amp;quot;,&#xA;    &amp;quot;uri&amp;quot;: &amp;quot;&amp;quot;} json.escape(if(req.http.Fastly-SSL, &amp;quot;https&amp;quot;, &amp;quot;http&amp;quot;) &#xA;    + &amp;quot;://&amp;quot; + req.http.host + req.url) + {&amp;quot;&amp;quot;,&#xA;    &amp;quot;user_agent&amp;quot;: &amp;quot;&amp;quot;} json.escape(req.http.User-Agent) {&amp;quot;&amp;quot;,&#xA;  },&#xA;  &amp;quot;network&amp;quot;: {&#xA;    &amp;quot;client&amp;quot;: {&#xA;      &amp;quot;ip&amp;quot;: &amp;quot;&amp;quot;} req.http.Fastly-Client-IP {&amp;quot;&amp;quot;,&#xA;    &amp;quot;server&amp;quot;: {&#xA;      &amp;quot;state&amp;quot;: &amp;quot;&amp;quot;} fastly_info.state {&amp;quot;&amp;quot;&#xA;    },&#xA;  },&#xA;  &amp;quot;timestamp&amp;quot;: &amp;quot;} time.start.msec {&amp;quot;,&#xA;  &amp;quot;timestamp_sec&amp;quot;: &amp;quot;} time.start.sec /* exists to support BigQuery */ {&amp;quot;}&#xA;}&amp;quot;};&#xA;&#xA;set var.json = regsuball(var.json, {&amp;quot;\s(?=([^&amp;quot;]*\&amp;quot;[^&amp;quot;]*&amp;quot;)*[^&amp;quot;]*$)&amp;quot;},&amp;quot;&amp;quot;);&#xA;&#xA;log var.json;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll admit this is definitely easier to read than the HTML encoding equivalent.&#xA;It&amp;rsquo;s still a bit confusing to get right, when creating big nested structures,&#xA;but no worse than a bunch of &lt;code&gt;%22&lt;/code&gt; throughout the structure 😬&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;restricting-requests-to-another-fastly-service&#34;&gt;Restricting requests to another Fastly service&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We had a requirement where by we had a request flow that looked something like&#xA;the following&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Client &amp;gt; Fastly (service: foo) &amp;gt; Fastly (service: bar) &amp;gt; Origin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this request flow both the Fastly services were managed by us (i.e. managed&#xA;by BuzzFeed) and we wanted to ensure that the service &lt;code&gt;bar&lt;/code&gt; could only accept&#xA;requests when they came via service &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We didn&amp;rsquo;t want to rely on HTTP request headers as these can be spoofed very&#xA;easily. Fastly suggested the following VCL based solution&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (!req.http.myservice &amp;amp;&amp;amp; (client.ip ~ fastly_ip_ranges))&#xA; error 808;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;808&lt;/code&gt; is a custom error status (see &lt;a href=&#34;#4.0&#34;&gt;Error Handling&lt;/a&gt; for more&#xA;context about using non-standard status codes). I typically prefer to use the&#xA;9xx range.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The idea being we can check if the &lt;code&gt;client.ip&lt;/code&gt; matches a known Fastly POP IP&#xA;range. If it doesn&amp;rsquo;t match that then we&amp;rsquo;ll reject the request. Additionally,&#xA;service &lt;code&gt;bar&lt;/code&gt; would check to see if a special request header was set by service&#xA;&lt;code&gt;foo&lt;/code&gt; (e.g. &lt;code&gt;set req.http.myservice = &amp;quot;yes&amp;quot;;&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An alternative approach also suggested by Fastly was to replace the IP check for&#xA;a request header check for a Fastly specific header &lt;code&gt;Fastly-FF&lt;/code&gt; (which is only&#xA;set when the request came from a Fastly POP):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.http.fastly-ff &amp;amp;&amp;amp; !req.http.myservice) {&#xA;  error 808;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-error-pages&#34;&gt;Custom Error Pages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Near the beginning of this post we looked at &lt;a href=&#34;#4.0&#34;&gt;error handling&lt;/a&gt; in VCL. I&#xA;want to now revisit this topic with regards to serving your own custom error&#xA;pages from the edge synthetically, so as to give you a real example of how this&#xA;might be put together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is example code that you can also run via &lt;a href=&#34;https://fiddle.fastlydemo.net/fiddle/cfd09f79&#34; target=&#34;_blank&#34;&gt;Fastly&amp;rsquo;s Fiddle&#xA;tool&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_recv {&#xA;  if (req.restarts == 1) {&#xA;    if (req.http.X-Error) {&#xA;      error std.strtol(req.http.X-Error, 10);&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;sub vcl_deliver {&#xA;  if (req.restarts == 0 &amp;amp;&amp;amp; resp.status &amp;gt;= 400) {&#xA;    if(fastly_info.state ~ &amp;quot;HIT($|-)&amp;quot;) {&#xA;      set req.http.X-FastlyInfoStatus = fastly_info.state;&#xA;      set req.http.X-CachedObjectHitCounter = obj.hits;&#xA;    }&#xA;    set req.http.X-Error = resp.status;&#xA;    return(restart);&#xA;  }&#xA;&#xA;  if (req.restarts == 1) {&#xA;    if (req.http.X-FastlyInfoStatus) {&#xA;      set resp.http.X-Cache = req.http.X-FastlyInfoStatus;&#xA;    }&#xA;    &#xA;    if (req.http.X-CachedObjectHitCounter) {&#xA;      set resp.http.X-Cache-Hits = std.strtol(req.http.X-CachedObjectHitCounter, 10);&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;vcl_error {&#xA;  synthetic {&amp;quot;&#xA;    &amp;lt;!doctype html&amp;gt;&#xA;    &amp;lt;html&amp;gt;&#xA;    &amp;lt;head&amp;gt;&#xA;      &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot;&amp;gt;&#xA;      &amp;lt;title&amp;gt;Page Not Found&amp;lt;/title&amp;gt;&#xA;      &amp;lt;meta name=&amp;quot;generator&amp;quot; content=&amp;quot;fastly&amp;quot;&amp;gt;&#xA;    &amp;lt;/head&amp;gt;&#xA;      &amp;lt;body&amp;gt;&#xA;        error happened&#xA;      &amp;lt;/body&amp;gt;&#xA;    &amp;lt;/html&amp;gt;&#xA;  &amp;quot;};&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The flow is actually quite simple once you have these pieces put together. The&#xA;principle of what we&amp;rsquo;re trying to achieve is that we want to serve a custom&#xA;error page from the edge server (rather than using the error page that may have&#xA;be sent by an origin).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way we&amp;rsquo;ll do this is that when we get the error response from the origin&#xA;we&amp;rsquo;ll restart the request and upon restarting the request we&amp;rsquo;ll trigger&#xA;&lt;code&gt;vcl_error&lt;/code&gt; (via the &lt;code&gt;error&lt;/code&gt; directive) and construct a synthetic response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we have that synthetic response we&amp;rsquo;ll also need to make some modifications&#xA;so that Fastly&amp;rsquo;s default VCL doesn&amp;rsquo;t make it look like we don&amp;rsquo;t get cache HITs&#xA;from future requests for this same resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This otherwise happens because Fastly&amp;rsquo;s default VCL has a basic check in&#xA;&lt;code&gt;vcl_deliver&lt;/code&gt; for an internal &amp;lsquo;hit&amp;rsquo; state which does occur, but then because we&#xA;restart the request and trigger &lt;code&gt;vcl_error&lt;/code&gt;, that internal hit state is replaced&#xA;by an &amp;lsquo;error&amp;rsquo; state and so it ends up confusing Fastly&amp;rsquo;s VCL logic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s dig into the code a bit&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So first of all we need to check in &lt;code&gt;vcl_deliver&lt;/code&gt; for an error status (and&#xA;because we plan on restarting the request, we don&amp;rsquo;t want to have an endless loop&#xA;so we&amp;rsquo;ll check the restart count as well):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.restarts == 0 &amp;amp;&amp;amp; resp.status &amp;gt;= 400) {&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we find we have indeed come from &lt;code&gt;vcl_hit&lt;/code&gt;, then we store off contextual&#xA;information about that cached object into the &lt;code&gt;req&lt;/code&gt; so it will persist the&#xA;restart and thus be usable later on when required:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set req.http.X-FastlyInfoStatus = fastly_info.state;&#xA;set req.http.X-CachedObjectHitCounter = obj.hits;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Regardless of whether we came from &lt;code&gt;vcl_hit&lt;/code&gt; or if we came from &lt;code&gt;vcl_fetch&lt;/code&gt;, we&#xA;store off the error response status code into the &lt;code&gt;req&lt;/code&gt; object so again we may&#xA;access it after the request is restarted:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set req.http.X-Error = resp.status;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, we&amp;rsquo;ll restart the request. At this point let&amp;rsquo;s now look at &lt;code&gt;vcl_recv&lt;/code&gt;&#xA;where we first check if we are dealing with a restart, and if so we extract the&#xA;response error status code and pass it over to &lt;code&gt;vcl_error&lt;/code&gt; by way of the &lt;code&gt;error&lt;/code&gt;&#xA;directive (notice we have to use a Fastly function to convert it from a STRING&#xA;to a INTEGER):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.restarts == 1) {&#xA;  if (req.http.X-Error) {&#xA;    error std.strtol(req.http.X-Error, 10);&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we reach &lt;code&gt;vcl_error&lt;/code&gt; we can now construct our custom error page. In the&#xA;example code I give I just use a single synthetic object to represent the error&#xA;but in real-life you&amp;rsquo;d check the status code provided to &lt;code&gt;vcl_error&lt;/code&gt; and then&#xA;construct a &lt;em&gt;specific&lt;/em&gt; error page. Once we create the object we jump back over&#xA;to &lt;code&gt;vcl_deliver&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;re back at &lt;code&gt;vcl_deliver&lt;/code&gt; for the second time you&amp;rsquo;ll find the first check&#xA;we had will no longer pass (avoiding an endless loop) but the second check&#xA;&lt;em&gt;will&lt;/em&gt; pass:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (req.restarts == 1) {&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we know we&amp;rsquo;re into the restarted request we can check the &lt;code&gt;req&lt;/code&gt; object for&#xA;the headers/information we were tracking earlier and use that information to&#xA;update two response headers that otherwise are set by Fastly: &lt;code&gt;X-Cache&lt;/code&gt; and&#xA;&lt;code&gt;X-Cache-Hits&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we need to override these two headers is because otherwise Fastly&#xA;records them as &lt;code&gt;X-Cache: MISS&lt;/code&gt; and &lt;code&gt;X-Cache-Hits: 0&lt;/code&gt; even after a secondary&#xA;request for the same resource. This would be concerning to people, because it&#xA;seems to suggest we went back to the origin again when we should have gotten a&#xA;cache HIT (we in fact &lt;em&gt;do&lt;/em&gt; get a cache HIT but Fastly is incorrectly reporting&#xA;that fact).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To understand what&amp;rsquo;s going on with Fastly incorrectly reporting the state of the&#xA;request, let&amp;rsquo;s look at the request flow&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Request 1&#xA;&#xA;vcl_recv &amp;gt; vcl_hash &amp;gt; vcl_miss &amp;gt; vcl_fetch &amp;gt; vcl_deliver (restart) &amp;gt; vcl_recv &amp;gt; vcl_error &amp;gt; vcl_deliver.&#xA;&#xA;# Request 2&#xA;&#xA;vcl_recv &amp;gt; vcl_hash &amp;gt; vcl_hit &amp;gt; vcl_deliver (restart) &amp;gt; vcl_recv &amp;gt; vcl_error &amp;gt; vcl_deliver.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For request 1 we have a cold cache scenario whereby the requested resource (e.g.&#xA;&lt;code&gt;/i-dont-exist&lt;/code&gt;) isn&amp;rsquo;t cached. So we go to the origin and the origin returns a&#xA;&lt;code&gt;404 Not Found&lt;/code&gt;. At that point &lt;code&gt;vcl_deliver&lt;/code&gt; identifies the error and restarts&#xA;the request. We construct a custom error page within &lt;code&gt;vcl_error&lt;/code&gt; and finally&#xA;serve the custom error page via &lt;code&gt;vcl_deliver&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After request 1 the response headers would suggest (correctly) that we got a&#xA;&lt;code&gt;X-Cache: MISS&lt;/code&gt; and &lt;code&gt;X-Cache-Hits: 0&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what happens if we request &lt;code&gt;/i-dont-exist&lt;/code&gt; again? Well, unless we fixed those&#xA;headers, the cache miss and zero hits would be reported again even though we&#xA;know that the second request got a cache HIT.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This happens because Fastly&amp;rsquo;s internal logic for setting &lt;code&gt;X-Cache: MISS&lt;/code&gt; and&#xA;&lt;code&gt;X-Cache-Hits&lt;/code&gt; looks a bit like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;set resp.http.X-Cache = if(resp.http.X-Cache, resp.http.X-Cache &amp;quot;, &amp;quot;,&amp;quot;&amp;quot;) &#xA;if(fastly_info.state ~ &amp;quot;HIT($|-)&amp;quot;, &amp;quot;HIT&amp;quot;, &amp;quot;MISS&amp;quot;);&#xA;&#xA;if(!resp.http.X-Cache-Hits) {&#xA;  set resp.http.X-Cache-Hits = obj.hits;&#xA;} else {&#xA;  set resp.http.X-Cache-Hits = resp.http.X-Cache-Hits &amp;quot;, &amp;quot; obj.hits;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Even though the second request gets a cache HIT for the origin&amp;rsquo;s &lt;em&gt;original&lt;/em&gt;&#xA;error response, the serving of the custom error page from the edge causes the&#xA;Fastly internal state (i.e. &lt;code&gt;fastly_info.state&lt;/code&gt;) to report as &lt;code&gt;ERROR&lt;/code&gt; instead of&#xA;a &lt;code&gt;HIT&lt;/code&gt; (&lt;em&gt;that&lt;/em&gt; happens because we call &lt;code&gt;error&lt;/code&gt; from within &lt;code&gt;vcl_recv&lt;/code&gt; after&#xA;restarting the request).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/computer-says-no.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/computer-says-no.webp&#34; alt=&#34;computer says no&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why when we get back into &lt;code&gt;vcl_deliver&lt;/code&gt; we override those headers&#xA;according to the values we tracked within the initial request flow.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;security&#34;&gt;Security&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are some aspects of the CDN where you need to take extra precautions to&#xA;protect your upstreams (and in some cases your customers data!). Let&amp;rsquo;s dig into&#xA;some of the concepts&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;rate-limiting&#34;&gt;Rate Limiting&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Rate limiting clients at the edge currently (as of March 2020) isn&amp;rsquo;t easy&#xA;because we don&amp;rsquo;t have a fully fledged programming environment to work with&#xA;(although Fastly is releasing a new &amp;lsquo;compute@edge&amp;rsquo; serverless service which aims&#xA;to tackle that problem).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there&amp;rsquo;s an alternative approach to what I discuss below, and it is&#xA;slightly more involved because it attempts to handle web scraper/fuzzer tools.&#xA;I&amp;rsquo;ve blogged about it as a separate article here: &lt;a href=&#34;/posts/rate-limiting/&#34;&gt;Rate Limiting at the CDN&#xA;Edge&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the mean time this leaves us with various ways of implementing rate limiting&#xA;with Fastly&amp;rsquo;s version of Varnish and VCL. One approach I have is a multi-pronged&#xA;approach and it ultimately requires your origin (or at least some service&#xA;&lt;em&gt;behind&lt;/em&gt; Fastly) to handle the rate limiting and to be able to return &lt;code&gt;429 Too Many Requests&lt;/code&gt; for a client that is hitting certain exposed endpoints too hard.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have rate limiting in place, the next question becomes: how can I&#xA;leverage the CDN and the edge to help protect my origin and its infrastructure&#xA;from having to handle requests that my origin will just end up rejecting with a&#xA;&lt;code&gt;429&lt;/code&gt; response any way?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For this, I present to you a solution that works like so:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We initially allow POST, PUT and DELETE requests to be looked up in the cache&#xA;(they&amp;rsquo;re typically uncached because they&amp;rsquo;ll usually result in exposing sensitive&#xA;data if otherwise cached and returned as a cache HIT to multiple clients).&lt;/li&gt;&#xA;&lt;li&gt;Once we get a response back from the origin we check if the status was a &lt;code&gt;429&lt;/code&gt;&#xA;and if so we assign a &lt;code&gt;Vary&lt;/code&gt; header and we set the response to be cacheable&#xA;(because &lt;code&gt;429&lt;/code&gt; status isn&amp;rsquo;t cached by default).&lt;/li&gt;&#xA;&lt;li&gt;If the response was a &lt;code&gt;200 OK&lt;/code&gt; for a POST request, then we&amp;rsquo;ll skip storing the&#xA;response in the cache.&lt;/li&gt;&#xA;&lt;li&gt;To ensure POST, PUT and DELETE requests don&amp;rsquo;t become sequentially blocking&#xA;requests when doing cache lookups, we&amp;rsquo;ll utilize &lt;code&gt;req.hash_ignore_busy&lt;/code&gt; to&#xA;disable &lt;a href=&#34;#request-collapsing&#34;&gt;request collapsing&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s what the code looks like (it makes changes to two states: &lt;code&gt;vcl_recv&lt;/code&gt; and&#xA;&lt;code&gt;vcl_fetch&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sub vcl_recv {&#xA;  if (req.restarts == 0) {&#xA;    if (!req.http.User-Agent) {&#xA;      set req.http.UserAgent = &amp;quot;Fallback&amp;quot;;&#xA;    }&#xA;  }&#xA;&#xA;  // force cache &#39;lookup&#39; for methods that are otherwise normally uncached&#xA;  // and mimic the standard behaviour of disabling &#39;request collapsing&#39;&#xA;  if (req.method ~ &amp;quot;(POST|PUT|DELETE)&amp;quot;) {&#xA;    set req.http.X-PassMethod = &amp;quot;true&amp;quot;;&#xA;    set req.hash_ignore_busy = true;&#xA;    return(lookup);&#xA;  }&#xA;}&#xA;    &#xA;sub vcl_fetch {&#xA;  // this conditional is used for testing the logic&#xA;  // and isn&#39;t required for actual implementation&#xA;  if (req.http.X-429) {&#xA;    set beresp.status = 429;&#xA;  }&#xA;&#xA;  declare local var.vary STRING;&#xA;  set var.vary = &amp;quot;Fastly-Client-IP, User-Agent&amp;quot;;&#xA;&#xA;  if (beresp.status == 429) {&#xA;    if (!beresp.http.Vary) {&#xA;      set beresp.http.Vary = var.vary;&#xA;    } else {&#xA;      set beresp.http.Vary = beresp.http.Vary + &amp;quot;, &amp;quot; + var.vary;&#xA;    }&#xA;&#xA;    set beresp.cacheable = true;&#xA;    if (!beresp.http.Surrogate-Control:max-age &amp;amp;&amp;amp; !beresp.http.Cache-Control:max-age) {&#xA;      set beresp.ttl = 1m; // 1 minute&#xA;    }&#xA;  }&#xA;&#xA;  if (req.http.X-PassMethod) {&#xA;    if (beresp.status != 429) {&#xA;      set beresp.cacheable = false;&#xA;    }&#xA;  }&#xA;&#xA;  return(deliver);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should pay attention to the fact that we Vary on the client&amp;rsquo;s IP and their&#xA;User-Agent, both of which can be changed. So it&amp;rsquo;s important to realize this&#xA;solution doesn&amp;rsquo;t solve DDoS attacks, and in some cases won&amp;rsquo;t help with standard&#xA;DoS attacks if the attacker is rotating their IP or User-Agent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One caveat to this approach (as noted by Fastly) is as follows:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;POST requests are also ineligible for clustering, ie transferring the request&#xA;to a consistently-hashed storage node. Since we don&amp;rsquo;t expect POSTs to be&#xA;cached, this is an optimisation and we unfortunately don&amp;rsquo;t provide a way for&#xA;you to override it. The effect of this is that even if you do enable POSTs to&#xA;be cached, your cache hit ratio will be poor. This may be fine if your&#xA;intention is just to use it for rate limiting.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;One thing you might be wondering is why I chose to allow &lt;code&gt;return(lookup)&lt;/code&gt; on&#xA;POST, PUT and DELETE methods, then set the response to cacheable in &lt;code&gt;vcl_fetch&lt;/code&gt;,&#xA;rather than keep the typical boilerplate logic which would check for those&#xA;methods and then &lt;code&gt;return(pass)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because once a request has been &amp;lsquo;passed&amp;rsquo; in &lt;code&gt;vcl_recv&lt;/code&gt; then it can&amp;rsquo;t be&#xA;set to be cacheable later (in &lt;code&gt;vcl_fetch&lt;/code&gt;) as we would have disabled caching&#xA;completely. You&amp;rsquo;ll be able to see tell this if you check the special&#xA;&lt;code&gt;fastly_info.state&lt;/code&gt; variable (or test the code via &lt;a href=&#34;https://fiddle.fastlydemo.net/fiddle/47871720&#34; target=&#34;_blank&#34;&gt;fastly&amp;rsquo;s fiddle&#xA;tool&lt;/a&gt;) as this will report back a&#xA;&lt;code&gt;pass&lt;/code&gt; state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/banned.webp&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/banned.webp&#34; alt=&#34;banned&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;path-traversal&#34;&gt;Path Traversal&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A path traversal vulnerability is the ability to craft a request that will cause&#xA;the server to make a request to somewhere different to what the request would&#xA;initially suggest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is best explained by a real example. This isn&amp;rsquo;t a real example in the sense&#xA;of a real vulnerability, we&amp;rsquo;re just going to utilize two separate tools (curl&#xA;and httpbin.org) to help us understand the &lt;em&gt;concept&lt;/em&gt; of the vulnerability.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we&amp;rsquo;ll use the popular &lt;a href=&#34;https://httpbin.org/&#34; target=&#34;_blank&#34;&gt;httpbin.org&lt;/a&gt; service as an&#xA;upstream server. The service provides (among many others) the endpoint&#xA;&lt;code&gt;/status/200&lt;/code&gt; which will return a &lt;code&gt;200 OK&lt;/code&gt; response, but it also provides an&#xA;&lt;code&gt;/anything&lt;/code&gt; endpoint which will display JSON data about the incoming request&#xA;(including the path you specified).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I made a request to &lt;code&gt;https://httpbin.org/anything/foo&lt;/code&gt; then it would show&#xA;&lt;code&gt;/anything/foo&lt;/code&gt; as the request path.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is the request we&amp;rsquo;re going to make (pay attention to the path):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl -v &amp;quot;https://httpbin.org/status/200/../../anything/status/404/&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This ^^ request has &lt;code&gt;../../&lt;/code&gt; inside of it, which curl (and this all depends on&#xA;the server and/or the software you test with/against) will &lt;em&gt;collapse&lt;/em&gt; down. This&#xA;means the request path becomes &lt;code&gt;/anything/status/404&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see the response from httpbin.org was:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  &amp;quot;args&amp;quot;: {},&#xA;  &amp;quot;data&amp;quot;: &amp;quot;&amp;quot;,&#xA;  &amp;quot;files&amp;quot;: {},&#xA;  &amp;quot;form&amp;quot;: {},&#xA;  &amp;quot;headers&amp;quot;: {&#xA;    &amp;quot;Accept&amp;quot;: &amp;quot;*/*&amp;quot;,&#xA;    &amp;quot;Host&amp;quot;: &amp;quot;httpbin.org&amp;quot;,&#xA;    &amp;quot;User-Agent&amp;quot;: &amp;quot;curl/7.64.1&amp;quot;,&#xA;    &amp;quot;X-Amzn-Trace-Id&amp;quot;: &amp;quot;Root=1-5f48c827-200a853c97290c8e6fce74ca&amp;quot;&#xA;  },&#xA;  &amp;quot;json&amp;quot;: null,&#xA;  &amp;quot;method&amp;quot;: &amp;quot;GET&amp;quot;,&#xA;  &amp;quot;origin&amp;quot;: &amp;quot;185.192.70.151&amp;quot;,&#xA;  &amp;quot;url&amp;quot;: &amp;quot;https://httpbin.org/anything/status/404/&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can actually tell curl to &lt;em&gt;not&lt;/em&gt; collapse the path when it sees&#xA;&lt;code&gt;../../&lt;/code&gt;, by using the &lt;code&gt;--path-as-is&lt;/code&gt; flag, and so if we made the earlier&#xA;request with this flag added, then httpbin.org would have rejected the request&#xA;as it wouldn&amp;rsquo;t have a route defined on the server end that recognized the full&#xA;path.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can now see how this might be a very dangerous attack because you could&#xA;construct a request to a server and trick it into communicating with any&#xA;private/internal APIs it has access to. In essence this type of attack could&#xA;enable the caller to access whatever data the server would normally only have&#xA;direct access to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how can we prevent this from happening? Well the solution is to parse the&#xA;request looking for invalid characters such as &lt;code&gt;..&lt;/code&gt; or the encoded variation of&#xA;a &lt;code&gt;.&lt;/code&gt; which is &lt;code&gt;%2E&lt;/code&gt;. This can happen at the application layer but I prefer to&#xA;handle this at the edge so our upstream services and infrastructure don&amp;rsquo;t have&#xA;to deal with the request at all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example of some VCL that handles this (it&amp;rsquo;s a separate file&#xA;&lt;code&gt;security.vcl&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// services that include this shared VCL should ensure they do not utilize the&#xA;// same error code, otherwise they may end up sending the wrong response.&#xA;//&#xA;&#xA;sub security_recv {&#xA;  // we want to prevent path traversal vulnerabilities such as:&#xA;  //&#xA;  // curl -v &amp;quot;https://httpbin.org/status/200/../../anything/status/404/&amp;quot;&#xA;  //&#xA;  // this ^^ would cause the server to go to /anything/status/404/ not /status/200&#xA;  //&#xA;  // this could be an issue because the upstream server might be able to&#xA;  // communicate with private/internal APIs, and so this type of attack could&#xA;  // enable the caller to access whatever data the server would normally only&#xA;  // have access to.&#xA;  //&#xA;  // example pattern match:&#xA;  // https://regex101.com/r/RYhmwW/2&#xA;  //&#xA;  // NOTES:&#xA;  // we utilize a &#39;long string&#39; {&amp;quot;...&amp;quot;} instead of a string literal &amp;quot;...&amp;quot;&#xA;  // to avoid interpretting the %2E as a period character when VCL statically&#xA;  // compiles a regex (which would change the pattern quite significantly!)&#xA;  //&#xA;  // DOCUMENTATION:&#xA;  // https://developer.fastly.com/reference/vcl/types/string/&#xA;  //&#xA;  if (req.url.path ~ {&amp;quot;(?i)(\.|%2E){2}(/|%2F)&amp;quot;}) {&#xA;    error 699 &amp;quot;Bad Request&amp;quot;;&#xA;  }&#xA;}&#xA;&#xA;sub security_error {&#xA;  if (obj.status == 699) {&#xA;    set obj.status = 400;&#xA;    synthetic {&amp;quot;Bad Request&amp;quot;};&#xA;    return(deliver);&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then include this file into your &lt;code&gt;main.vcl&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;include &amp;quot;security&amp;quot;&#xA;&#xA;sub vcl_recv {&#xA;  #FASTLY recv&#xA;&#xA;  call security_recv;&#xA;&#xA;  return(lookup);&#xA;}&#xA;&#xA;sub vcl_error {&#xA;  #FASTLY error&#xA;&#xA;  call security_error;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;CAREFUL! when VCL statically compiles a regex it will attempt to&#xA;&amp;lsquo;interpret&amp;rsquo; it unless the string literal (used to provide the regex pattern)&#xA;is a &amp;lsquo;long string&amp;rsquo; such as &lt;code&gt;{&amp;quot;...&amp;quot;}&lt;/code&gt;. Please refer to the &lt;a href=&#34;https://developer.fastly.com/reference/vcl/types/string/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;string&lt;/code&gt;&#xA;documentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So there we have it, a run down of how some important aspects of Varnish and VCL&#xA;work (and specifically for Fastly&amp;rsquo;s implementation).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One thing I want to mention is that I am personally a HUGE fan of Fastly and the&#xA;tools they provide. They are an amazing company and their software has helped&#xA;BuzzFeed (and many other large organisations) to scale massively with ease.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ve been a wonderful audience. Hope you enjoyed this post. Be sure to tip&#xA;your waiter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And remember&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://media.giphy.com/media/iIj82XyyYM12YT5Hlm/giphy.gif&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;https://media.giphy.com/media/iIj82XyyYM12YT5Hlm/giphy.gif&#34; alt=&#34;&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-material&#34;&gt;Reference material&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I would highly recommend watching this talk by Rogier Mulhuijzen (Senior Varnish&#xA;Engineer - who currently works for Fastly) on &amp;ldquo;Advanced VCL&amp;rdquo;:&#xA;&lt;a href=&#34;https://vimeo.com/226067901&#34; target=&#34;_blank&#34;&gt;vimeo.com/226067901&lt;/a&gt;. It goes into great detail&#xA;about some complex aspects of VCL and Varnish and really does a great job of&#xA;elucidating them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also recommended is &lt;a href=&#34;https://vimeo.com/178057523&#34; target=&#34;_blank&#34;&gt;this Fastly talk&lt;/a&gt; which&#xA;details how &amp;lsquo;clustering&amp;rsquo; works (see also &lt;a href=&#34;https://support.fastly.com/hc/en-us/community/posts/360040445272--Fastly-Force-Shield-AND-Fastly-No-Shield-Usage&#34; target=&#34;_blank&#34;&gt;this fastly community support&#xA;post&lt;/a&gt;&#xA;that details how to utilize the request headers &lt;code&gt;Fastly-Force-Shield&lt;/code&gt; and&#xA;&lt;code&gt;Fastly-No-Shield&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly there is &lt;a href=&#34;https://vimeo.com/showcase/6623864/video/376921467&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt; talk&#xA;about &lt;code&gt;vcl_fetch&lt;/code&gt; that also covers clustering and shielding, that can help tie&#xA;up any other loose ends related to Fastly&amp;rsquo;s system design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, there was &lt;a href=&#34;https://medium.com/@samparkinson_/making-a-request-to-the-financial-times-b2119a2f422d&#34; target=&#34;_blank&#34;&gt;a recent article from an engineer working at the Financial&#xA;Times&lt;/a&gt;,&#xA;detailing the complete request flow from DNS to Delivery. It&amp;rsquo;s very interesting&#xA;and covers a lot of information about Fastly. Highly recommended reading.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/fastly-varnish/</guid>
      <link>https://www.integralist.co.uk/posts/fastly-varnish/</link>
      <pubDate>Thu, 02 Nov 2017 00:00:00 +0000</pubDate>
      <title>Fastly Varnish</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;memory-management&#34;&gt;Memory Management&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before we dive into the techniques and tools available for profiling Python applications, we should first understand a little bit about its memory model as this can help us to understand what it is we’re seeing in relation to memory consumption.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Python manages memory using &lt;strong&gt;reference counting&lt;/strong&gt; semantics. What this means is, every time an object is referenced, either by a variable assignment or similar, the counter for that object is incremented. Once an object is not referenced anymore its memory is deallocated (its counter is decremented every time a reference is removed, until it reaches zero). But as long as there is a reference (somewhere in the program), then the object will not be deallocated (as the internal counter will be greater than zero).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now this can cause &lt;a href=&#34;http://engineering.hearsaysocial.com/2013/06/16/circular-references-in-python/&#34; target=&#34;_blank&#34;&gt;problems&lt;/a&gt; when dealing with &lt;a href=&#34;https://stackoverflow.com/questions/9910774/what-is-a-reference-cycle-in-python&#34; target=&#34;_blank&#34;&gt;cyclical references&lt;/a&gt;, so that&amp;rsquo;s something to be aware of when investigating memory leaks and other memory related concerns.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for lots of details of how Python allocates memory, I highly recommend &lt;a href=&#34;https://dmalcolm.fedorapeople.org/presentations/PyCon-US-2011/MemoryUsage.pdf&#34; target=&#34;_blank&#34;&gt;this presentation&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;types-of-profiling&#34;&gt;Types of Profiling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are a couple of approaches available to us for monitoring performance&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Timers&lt;/strong&gt;: useful for benchmarking, as well as comparing &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; fixes.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Profilers&lt;/strong&gt;: useful for high-level verification.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;tools-matrix&#34;&gt;Tools Matrix&lt;/h2&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;&lt;/th&gt;&#xA;&lt;th&gt;Pros&lt;/th&gt;&#xA;&lt;th&gt;Cons&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#5&#34;&gt;timer (decorator)&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Simple, quick and easy.&lt;/td&gt;&#xA;&lt;td&gt;- Requires code change.&lt;br&gt;- Adds latency &amp;amp; skews results.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#6&#34;&gt;timeit module&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Calculate repeat averages.&lt;br&gt;- Doesn’t require code change.&lt;/td&gt;&#xA;&lt;td&gt;- More complicated API.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#7&#34;&gt;profiler module&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Granular CPU by file.&lt;br&gt;- Can be run from terminal.&lt;/td&gt;&#xA;&lt;td&gt;- More complicated results.&lt;br&gt;- Read docs to understand.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#8&#34;&gt;line_profiler&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Granular line-by-line CPU.&lt;/td&gt;&#xA;&lt;td&gt;- Slow.&lt;br&gt;- Not built-in package.&lt;br&gt;- Requires code change.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#9&#34;&gt;memory_profiler&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Clear and easy results.&lt;/td&gt;&#xA;&lt;td&gt;- Slow †&lt;br&gt;- Not built-in package.&lt;br&gt;- † additional packages help.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#10&#34;&gt;tracemalloc&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Built-in memory package.&lt;/td&gt;&#xA;&lt;td&gt;- Requires code change.&lt;br&gt;- More complicated API.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#11&#34;&gt;pyflame&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Visualise problem area easily.&lt;br&gt;- Details CPU and Memory&lt;/td&gt;&#xA;&lt;td&gt;- Requires Linux.&lt;br&gt;- Most complex to setup.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 id=&#34;analysis-steps&#34;&gt;Analysis Steps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Regardless of the tool you use for analysis, a general rule of thumb is to:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Identify a bottleneck at a high-level&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For example, you might notice a long running function call.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Reduce the operations&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Look at time spent, or number of calls, and figure out an alternative approach.&lt;/li&gt;&#xA;&lt;li&gt;Look at the number of memory allocations, figure out an alternative approach.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Drill down&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use a tool that gives you data at a lower-level.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Think about more performant algorithms or data structures.&lt;br&gt;&#xA;There may also be simpler solutions.&lt;br&gt;&#xA;Take a pragmatic look at your code.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;base-example&#34;&gt;Base Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let’s begin with a simple program written using Python 3…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def get_number():&#xA;    for i in range(10000000):&#xA;        yield i&#xA;&#xA;&#xA;def expensive_function():&#xA;    for n in get_number():&#xA;        r = n ^ n ^ n&#xA;    return f&amp;quot;some result! {r}&amp;quot;&#xA;&#xA;&#xA;print(expensive_function())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I’m currently using Python version 3.6.3&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Running this program can take ~1.8 seconds and returns the value:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;some result! 9999999&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;timer&#34;&gt;Timer&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We can use a simple decorator to time the length of our &lt;code&gt;expensive_function&lt;/code&gt; call&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from time import time&#xA;from functools import wraps&#xA;&#xA;&#xA;def timefn(fn):&#xA;    &amp;quot;&amp;quot;&amp;quot;Simple timer decorator.&amp;quot;&amp;quot;&amp;quot;&#xA;    @wraps(fn)&#xA;    def measure_time(*args, **kwargs):&#xA;        t1 = time()&#xA;        result = fn(*args, **kwargs)&#xA;        t2 = time()&#xA;        print(f&amp;quot;@timefn: {fn.__name__} took {str(t2 - t1)} seconds&amp;quot;)&#xA;        return result&#xA;    return measure_time&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The problem with this approach is that the decorator results in additional latency. Meaning the program takes slightly longer to complete. Not a lot, but if you’re after precision then this can skew the results (which is a common theme when benchmarking or profiling).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;built-in-module-timeit&#34;&gt;Built-in module: timeit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The built-in &lt;a href=&#34;https://docs.python.org/3/library/timeit.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;timeit&lt;/code&gt;&lt;/a&gt; module is another simple way of benchmarking the time it takes for a function to execute. Simply import the module and call its interface.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import timeit&#xA;…&#xA;result = timeit.timeit(expensive_function, number=1)  # one repetition&#xA;print(result)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can tweak the number param to determine how many repetitions it’ll run.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Along with the &lt;code&gt;timeit&lt;/code&gt; method, there is a &lt;code&gt;repeat&lt;/code&gt; method that returns a set of averages across the number of repeated code executions.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;result = timeit.repeat(expensive_function, number=1, repeat=5)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this case result would contain something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[1.7263835030025803, 1.7080924350011628, 1.6802870190003887, 1.6736655100103235, 1.7003267239924753]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;according to the Python documentation when utilising the &lt;code&gt;repeat&lt;/code&gt; method you should only be interested in the &lt;code&gt;min()&lt;/code&gt; because…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;“In a typical case, the lowest value gives a lower bound for how fast your machine can run the given code snippet; higher values in the result vector are typically not caused by variability in Python’s speed, but by other processes interfering with your timing accuracy”.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Finally, there is also a command line version you can utilise:&lt;br&gt;&#xA;&lt;code&gt;python -m timeit&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;built-in-module-profiler&#34;&gt;Built-in module: profiler&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are two flavours of &lt;a href=&#34;https://docs.python.org/3/library/profile.html&#34; target=&#34;_blank&#34;&gt;profiler&lt;/a&gt;, a pure Python version (&lt;code&gt;import profile&lt;/code&gt;) and a C extension version (&lt;code&gt;import cProfile&lt;/code&gt;) which is preferred, as the former is remarkably slower.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, the C profile took ~3 seconds to complete,&#xA;whereas the Python version took over a minute.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if using &lt;code&gt;cProfile&lt;/code&gt; you would execute: &lt;code&gt;cProfile.run(&amp;quot;expensive_function()&amp;quot;)&lt;/code&gt; otherwise you would execute &lt;code&gt;profile.run(&amp;quot;expensive_function()&amp;quot;)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You should see something like the following displayed after executing your program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;         10000005 function calls in 3.132 seconds&#xA;&#xA;   Ordered by: standard name&#xA;&#xA;   ncalls  tottime  percall  cumtime  percall filename:lineno(function)&#xA; 10000001    1.042    0.000    1.042    0.000 3_profile.py:4(get_number)&#xA;        1    2.090    2.090    3.132    3.132 3_profile.py:9(expensive_function)&#xA;        1    0.000    0.000    3.132    3.132 &amp;lt;string&amp;gt;:1(&amp;lt;module&amp;gt;)&#xA;        1    0.000    0.000    3.132    3.132 {built-in method builtins.exec}&#xA;        1    0.000    0.000    0.000    0.000 {method &#39;disable&#39; of &#39;_lsprof.Profiler&#39; objects}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So from these results we can see:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;There were a total of &lt;code&gt;10000005&lt;/code&gt; function calls.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;get_number&lt;/code&gt; function was called the most (&lt;code&gt;10000001&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Every other function in the total recorded, were called just the once.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;expensive_function&lt;/code&gt; took a total of 2.090 seconds (exc. sub function calls).&lt;/li&gt;&#xA;&lt;li&gt;The cumulative time (&lt;code&gt;cumtime&lt;/code&gt;) is the &lt;code&gt;tottime&lt;/code&gt; plus sub function calls.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when there are two numbers in the first column (for example &lt;code&gt;3/1&lt;/code&gt;), it means that the function recursed. The second value is the number of primitive calls and the former is the total number of calls. Note that when the function does not recurse, these two values are the same, and only the single figure is printed.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Instead of printing the results you can pass the run method a second argument which is a filename you want to store the results in. Once there you can use the &lt;a href=&#34;https://docs.python.org/3/library/profile.html#pstats.Stats&#34; target=&#34;_blank&#34;&gt;pstats.Stats&lt;/a&gt; module to carry out some post-processing on those results.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, there is also a command line version you can utilise:&lt;br&gt;&#xA;&lt;code&gt;python -m cProfile [-o output_file] [-s sort_order] &amp;lt;your_script.py&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;line-profiler&#34;&gt;Line Profiler&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://pypi.python.org/pypi/line_profiler&#34; target=&#34;_blank&#34;&gt;Line Profiler&lt;/a&gt; option gives much more granular detail than the built-in profile module, but it is an external package and so needs to be installed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pip install line_profiler&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once installed you can write a decorator to wrap the functionality and make it easier for applying to specific functions you want to profile (as demonstrated below).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from line_profiler import LineProfiler&#xA;&#xA;&#xA;def do_profile(follow=None):&#xA;    if not follow:&#xA;        follow = []&#xA;&#xA;    def inner(func):&#xA;        def profiled_func(*args, **kwargs):&#xA;            try:&#xA;                profiler = LineProfiler()&#xA;                profiler.add_function(func)&#xA;                for f in follow:&#xA;                    profiler.add_function(f)&#xA;                profiler.enable_by_count()&#xA;                return func(*args, **kwargs)&#xA;            finally:&#xA;                profiler.print_stats()&#xA;        return profiled_func&#xA;    return inner&#xA;&#xA;&#xA;def get_number():&#xA;    for i in range(10000000):&#xA;        yield i&#xA;&#xA;&#xA;@do_profile(follow=[get_number])&#xA;def expensive_function():&#xA;    for n in get_number():&#xA;        r = n ^ n ^ n&#xA;    return f&amp;quot;some result! {r}&amp;quot;&#xA;&#xA;&#xA;print(expensive_function())&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see the result of executing this program below…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Timer unit: 1e-06 s&#xA;&#xA;Total time: 7.59566 s&#xA;File: 4_line_profile.py&#xA;Function: get_number at line 23&#xA;&#xA;Line #      Hits         Time  Per Hit   % Time  Line Contents&#xA;==============================================================&#xA;    23                                           def get_number():&#xA;    24  10000001      3924533      0.4     51.7      for i in range(10000000):&#xA;    25  10000000      3671129      0.4     48.3          yield i&#xA;&#xA;Total time: 27.477 s&#xA;File: 4_line_profile.py&#xA;Function: expensive_function at line 28&#xA;&#xA;Line #      Hits         Time  Per Hit   % Time  Line Contents&#xA;==============================================================&#xA;    28                                           @do_profile(follow=[get_number])&#xA;    29                                           def expensive_function():&#xA;    30  10000001     22122124      2.2     80.5      for n in get_number():&#xA;    31  10000000      5354911      0.5     19.5          r = n ^ n ^ n&#xA;    32         1            3      3.0      0.0      return f&amp;quot;some result! {r}&amp;quot;&#xA;&#xA;some result! 9999999&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the Line Profiler is pretty slow (~35s) in comparison to the cProfiler (~4s)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The Line Profiler will typically only analyse the function being decorated. In order for it to include sub function calls, you’ll need to specify them (hence the decorator allows you to provide a list of functions and in there we’ve specified the &lt;code&gt;get_number&lt;/code&gt; function).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The order in which you list the sub functions to ‘follow’ doesn’t matter, as the results will always display (top to bottom) the deepest nested sub function to the top level function (so we can see that &lt;code&gt;get_number&lt;/code&gt; is nested inside of &lt;code&gt;expensive_function&lt;/code&gt; and so it is top of the output).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From these results we can get a line-by-line breakdown of how long (in percentages) each function took to complete. So &lt;code&gt;expensive_function&lt;/code&gt; spent ~20% of its time calculating a value to assign to the variable &lt;code&gt;r&lt;/code&gt;, and the remaining 80% was spent calculating a value to assign to the variable &lt;code&gt;n&lt;/code&gt; (which was the call out to the &lt;code&gt;get_number&lt;/code&gt; function).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As for &lt;code&gt;get_number&lt;/code&gt;, it was approximately &lt;sup&gt;50&lt;/sup&gt;&amp;frasl;&lt;sub&gt;50&lt;/sub&gt; for time between looping the &lt;code&gt;range(10000000)&lt;/code&gt; and &lt;code&gt;yield&lt;/code&gt;’ing a value back to the caller context (i.e. &lt;code&gt;expensive_function&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, there is also a command line version you can utilise:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;kernprof -l [-v view_results] &amp;lt;your_script.py&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you omit the &lt;code&gt;-l&lt;/code&gt; flag, then you can view the results at a later time using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;python -m line_profiler &amp;lt;your_script.py&amp;gt;.lprof&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;basic-memory-profiler&#34;&gt;Basic Memory Profiler&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There is a module called &lt;code&gt;memory_profiler&lt;/code&gt; which is very simple to use, although with the example code we’ve been using it was so painfully slow it was pretty much unusable (I gave up after 5 minutes of waiting). So, because of that issue, I’ll demonstrate a simpler example.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But first you need to install the module:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pip install memory_profiler&#xA;pip install psutil  # recommended to help speed up the reporting time&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you can import the decorator, and apply that to our &lt;em&gt;new&lt;/em&gt; ‘slow’ function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;from memory_profiler import profile&#xA;&#xA;@profile&#xA;def expensive_memory_allocations():&#xA;    a = [1] * (10 ** 6)&#xA;    b = [2] * (2 * 10 ** 7)&#xA;    del b&#xA;    return a&#xA;&#xA;print(len(expensive_memory_allocations()))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When you run this program, you’ll see a memory breakdown similar to the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Line #    Mem usage    Increment   Line Contents&#xA;================================================&#xA;    35     27.8 MiB      0.0 MiB   @profile&#xA;    36                             def beep():&#xA;    37     35.4 MiB      7.6 MiB       a = [1] * (10 ** 6)&#xA;    38    188.0 MiB    152.6 MiB       b = [2] * (2 * 10 ** 7)&#xA;    39     35.4 MiB   -152.6 MiB       del b&#xA;    40     35.4 MiB      0.0 MiB       return a&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The second column “Mem usage” indicates the memory consumption for the Python interpreter after that line was executed. The third column “Increment” indicates the difference in increased memory compared to the previous line that was executed. So you can see, for example, when we delete the &lt;code&gt;b&lt;/code&gt; variable we are able to reclaim the memory it was holding on to.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tracemalloc&#34;&gt;Tracemalloc&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There is another basic memory profiler that provides similar features called &lt;a href=&#34;https://docs.python.org/3/library/tracemalloc.html&#34; target=&#34;_blank&#34;&gt;tracemalloc&lt;/a&gt; but this particular tool is part of the standard library in Python so it might be preferable to the external library &lt;a href=&#34;#9&#34;&gt;memory_profiler&lt;/a&gt; (shown earlier).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;import tracemalloc&#xA;&#xA;&#xA;def get_number():&#xA;    for i in range(10000000):&#xA;        yield i&#xA;&#xA;&#xA;def expensive_function():&#xA;    for n in get_number():&#xA;        r = n ^ n ^ n&#xA;    return f&amp;quot;some result! {r}&amp;quot;&#xA;&#xA;&#xA;tracemalloc.start()&#xA;&#xA;print(expensive_function())&#xA;&#xA;snapshot = tracemalloc.take_snapshot()&#xA;top_stats = snapshot.statistics(&amp;quot;lineno&amp;quot;)&#xA;&#xA;print(&amp;quot;[ Top 10 ]&amp;quot;)&#xA;for stat in top_stats[:10]:&#xA;    print(stat)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output from this example is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ time python tracemalloc_example.py&#xA;&#xA;some result! 9999999&#xA;&#xA;[ Top 10 ]&#xA;tracemalloc_example.py:17: size=106 B, count=2, average=53 B&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You might also consider &lt;a href=&#34;https://pythonhosted.org/Pympler/muppy.html&#34; target=&#34;_blank&#34;&gt;Pympler&lt;/a&gt; or &lt;a href=&#34;http://mg.pov.lt/objgraph/&#34; target=&#34;_blank&#34;&gt;ObjGraph&lt;/a&gt; for tracking memory usage &amp;amp; object refs.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;pyflame-flame-graphs&#34;&gt;PyFlame (Flame Graphs)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Flame graphs are a visualization of profiled software (stack traces), allowing the most frequent code-paths to be identified quickly and accurately. Flame graphs allows hot code-paths to be identified quickly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/uber/pyflame&#34; target=&#34;_blank&#34;&gt;PyFlame&lt;/a&gt; is an effective tool (written in C++) for generating flame graph data, which can help you to understand the CPU and memory characteristics of your services. In some cases it can report more accurate results than those provided by the built-in Python modules.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For more details on the design decisions behind PyFlame and the shortcomings of the other built-in options, then I would recommend reading &lt;a href=&#34;https://eng.uber.com/pyflame/&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PyFlame only works with Linux operating systems and so in order to profile our code (if you’re using macOS like I am), then we’ll have to utilise &lt;a href=&#34;https://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt; to help us. Below is a &lt;code&gt;Dockerfile&lt;/code&gt; you can use as a basic starting point to try out PyFlame.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we also require &lt;a href=&#34;https://github.com/brendangregg/FlameGraph&#34; target=&#34;_blank&#34;&gt;FlameGraph&lt;/a&gt; in order to generate the flame graphs.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM python:3.6.3&#xA;&#xA;WORKDIR /pyflame&#xA;&#xA;# Install dependencies required to ‘build’ PyFlame&#xA;RUN apt-get update -y&#xA;RUN apt-get install -y git autoconf automake autotools-dev g++ pkg-config python-dev python3-dev libtool make&#xA;&#xA;# Build PyFlame&#xA;RUN git clone https://github.com/uber/pyflame.git &amp;amp;&amp;amp; \&#xA;    cd pyflame &amp;amp;&amp;amp; ./autogen.sh &amp;amp;&amp;amp; ./configure &amp;amp;&amp;amp; make&#xA;&#xA;WORKDIR /flamegraph&#xA;&#xA;RUN git clone https://github.com/brendangregg/FlameGraph&#xA;&#xA;COPY 7_pyflame.py /app/app.py&#xA;&#xA;WORKDIR /app&#xA;&#xA;CMD /pyflame/pyflame/src/pyflame -o prof.txt -t python app.py &amp;amp;&amp;amp;\&#xA;    /flamegraph/FlameGraph/flamegraph.pl ./prof.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In order to build and run this &lt;code&gt;Dockerfile&lt;/code&gt;, you’ll need to execute the following code…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t pyflame .&#xA;&#xA;docker run --privileged pyflame &amp;gt; output.svg &amp;amp;&amp;amp; tail -n+2 output.svg &amp;gt; output_stripped.svg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;our application sends data to stdout (e.g. &lt;code&gt;some result! 9999999&lt;/code&gt;) and so this ends up at the top of our &lt;code&gt;output.svg&lt;/code&gt; file. This means we need to remove it. We could either modify the application code or you could do what I’ve done and strip it after the file is created by using the &lt;code&gt;tail&lt;/code&gt; command and redirecting the stripped output to a new file: &lt;code&gt;output_stripped.svg&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If we now open &lt;code&gt;output_stripped.svg&lt;/code&gt; we should see the following interactive flame graph.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/pyflame.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/pyflame.png&#34; alt=&#34;pyflame&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s our tour of various tools for profiling your Python code. I&amp;rsquo;ll follow this article up with a Go based one in the very near future. But if you&amp;rsquo;re interested in further reading then the following blog posts from rushter.com are worth a look:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://rushter.com/blog/python-garbage-collector/&#34; target=&#34;_blank&#34;&gt;Python Garbage Collection&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://rushter.com/blog/python-memory-managment/&#34; target=&#34;_blank&#34;&gt;Python Memory Management&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/profiling-python/</guid>
      <link>https://www.integralist.co.uk/posts/profiling-python/</link>
      <pubDate>Tue, 31 Oct 2017 00:00:00 +0000</pubDate>
      <title>Profiling Python</title>
    </item>
    <item>
      <description>&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I highly recommend also reading &lt;a href=&#34;https://golang.org/doc/diagnostics.html&#34; target=&#34;_blank&#34;&gt;this&lt;/a&gt; official diagnostics documentation.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;memory-management&#34;&gt;Memory Management&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before we dive into the techniques and tools available for profiling Go applications, we should first understand a little bit about its memory model as this can help us to understand what it is we’re seeing in relation to memory consumption.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go’s implementation is a &lt;em&gt;parallel&lt;/em&gt; &lt;a href=&#34;http://wiki.c2.com/?MarkAndSweep&#34; target=&#34;_blank&#34;&gt;mark-and-sweep garbage collector&lt;/a&gt;. In the &lt;em&gt;traditional&lt;/em&gt; mark-and-sweep model, the garbage collector would stop the program from running (i.e. “stop the world”) while it detects unreachable objects and again while it clears them (i.e. deallocates the memory). This is to prevent complications where the running program could end up moving references around during the identification/clean-up phase. This would also cause latency and other issues for users of the program while the GC ran. With Go the &lt;a href=&#34;https://blog.golang.org/go15gc&#34; target=&#34;_blank&#34;&gt;GC is executed concurrently&lt;/a&gt;, so users don’t notice pauses or delays even though the GC is running.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;types-of-profiling&#34;&gt;Types of Profiling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are a couple of approaches available to us for monitoring performance&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Timers&lt;/strong&gt;: useful for benchmarking, as well as comparing &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; fixes.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Profilers&lt;/strong&gt;: useful for high-level verification.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;tools-matrix&#34;&gt;Tools Matrix&lt;/h2&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;&lt;/th&gt;&#xA;&lt;th&gt;Pros&lt;/th&gt;&#xA;&lt;th&gt;Cons&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#5&#34;&gt;ReadMemStats&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Simple, quick and easy.&lt;br&gt;- Only details memory usage.&lt;/td&gt;&#xA;&lt;td&gt;- Requires code change.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#6&#34;&gt;pprof&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Details CPU and Memory.&lt;br&gt;- Remote analysis possible.&lt;br&gt;- Image generation.&lt;/td&gt;&#xA;&lt;td&gt;- Requires code change.&lt;br&gt;- More complicated API.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;&lt;a href=&#34;#7&#34;&gt;trace&lt;/a&gt;&lt;/td&gt;&#xA;&lt;td&gt;- Helps analyse data over time.&lt;br&gt;- Powerful debugging UI.&lt;br&gt;- Visualise problem area easily.&lt;/td&gt;&#xA;&lt;td&gt;- Requires code change.&lt;br&gt;- UI is complex.&lt;br&gt;- Takes time to understand.&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 id=&#34;analysis-steps&#34;&gt;Analysis Steps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Regardless of the tool you use for analysis, a general rule of thumb is to:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Identify a bottleneck at a high-level&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For example, you might notice a long running function call.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Reduce the operations&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Look at time spent, or number of calls, and figure out an alternative approach.&lt;/li&gt;&#xA;&lt;li&gt;Look at the number of memory allocations, figure out an alternative approach.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Drill down&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use a tool that gives you data at a lower-level.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Think about more performant algorithms or data structures.&lt;br&gt;&#xA;There may also be simpler solutions.&lt;br&gt;&#xA;Take a pragmatic look at your code.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;base-example&#34;&gt;Base Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let’s begin with a simple program written using Go 1.9.2…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;log&amp;quot;&#xA;)&#xA;&#xA;// bigBytes allocates 100 megabytes&#xA;func bigBytes() *[]byte {&#xA;    s := make([]byte, 100000000)&#xA;    return &amp;amp;s&#xA;}&#xA;&#xA;func main() {&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Running this program can take ~0.2 seconds to execute.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So this isn’t a slow program, we’re just using it as a base to measure memory consumption.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;readmemstats&#34;&gt;ReadMemStats&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The easiest way to look what our application is doing with regards to memory allocation is by utilising the &lt;code&gt;MemStats&lt;/code&gt; from the &lt;code&gt;runtime&lt;/code&gt; package.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following snippet we modify the &lt;code&gt;main&lt;/code&gt; function to print out specific memory statistics.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func main() {&#xA;    var mem runtime.MemStats&#xA;&#xA;    fmt.Println(&amp;quot;memory baseline...&amp;quot;)&#xA;&#xA;    runtime.ReadMemStats(&amp;amp;mem)&#xA;    log.Println(mem.Alloc)&#xA;    log.Println(mem.TotalAlloc)&#xA;    log.Println(mem.HeapAlloc)&#xA;    log.Println(mem.HeapSys)&#xA;&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;&#xA;    fmt.Println(&amp;quot;memory comparison...&amp;quot;)&#xA;&#xA;    runtime.ReadMemStats(&amp;amp;mem)&#xA;    log.Println(mem.Alloc)&#xA;    log.Println(mem.TotalAlloc)&#xA;    log.Println(mem.HeapAlloc)&#xA;    log.Println(mem.HeapSys)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If I run this program I’ll see the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;memory baseline…&#xA;&#xA;2017/10/29 08:51:56 56480&#xA;2017/10/29 08:51:56 56480&#xA;2017/10/29 08:51:56 56480&#xA;2017/10/29 08:51:56 786432&#xA;&#xA;memory comparison...&#xA;&#xA;2017/10/29 08:51:56 200074312&#xA;2017/10/29 08:51:56 1000144520&#xA;2017/10/29 08:51:56 200074312&#xA;2017/10/29 08:51:56 200704000&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see the difference between what the go application was using at the point in time that the &lt;code&gt;main&lt;/code&gt; function started and when it finished (after allocating a lot of memory via the &lt;code&gt;bigBytes&lt;/code&gt; function). The two items we’re most interested in are &lt;code&gt;TotalAlloc&lt;/code&gt; and &lt;code&gt;HeapAlloc&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The total allocations shows us the total amount of memory accumulated (this value &lt;em&gt;doesn’t&lt;/em&gt; decrease as memory is freed). Whereas the heap allocations indicate the amount of memory at the point in time when the snapshot was taken, and it can include &lt;em&gt;both&lt;/em&gt; reachable and unreachable objects (e.g. objects the garbage collector hasn’t freed yet). So it’s important to realise that the amount of memory ‘in use’ could have dropped after the snapshot was taken.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Take a look at the &lt;a href=&#34;https://golang.org/pkg/runtime/#MemStats&#34; target=&#34;_blank&#34;&gt;MemStats docs&lt;/a&gt; for more properties (inc. &lt;code&gt;Mallocs&lt;/code&gt; or &lt;code&gt;Frees&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;pprof&#34;&gt;Pprof&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/google/pprof&#34; target=&#34;_blank&#34;&gt;Pprof&lt;/a&gt; is a tool for visualization and analysis of profiling data.&lt;br&gt;&#xA;It’s useful for identifying where your application is spending its time (CPU and memory).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can install it using:&lt;br&gt;&#xA;&lt;code&gt;go get github.com/google/pprof&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To begin with, let’s understand what a “profile” is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A Profile is a collection of stack traces showing the call sequences that led to instances of a particular event, such as allocation. Packages can create and maintain their own profiles; the most common use is for tracking resources that must be explicitly closed, such as files or network connections. &amp;ndash; &lt;a href=&#34;https://golang.org/pkg/runtime/pprof/#Profile&#34; target=&#34;_blank&#34;&gt;pkg/runtime/pprof&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now there are a couple of ways to use this tool:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Instrument code within binary to generate a &lt;code&gt;.profile&lt;/code&gt; for analysis &lt;em&gt;during&lt;/em&gt; development.&lt;/li&gt;&#xA;&lt;li&gt;Remotely analyse binary via a web server (no &lt;code&gt;.profile&lt;/code&gt; is explicitly generated).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the profile file doesn’t have to use a &lt;code&gt;.profile&lt;/code&gt; extension (it can be whatever you like)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;generate-profile-for-analysis-during-development&#34;&gt;Generate .profile for analysis during development&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In this section we’ll look at profiling both CPU and Memory allocation.&lt;br&gt;&#xA;We’ll start with CPU profiling.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;cpu-analysis&#34;&gt;CPU Analysis&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;In the following example we’ve modified the application to import &lt;code&gt;&amp;quot;runtime/pprof&amp;quot;&lt;/code&gt; and added the relevant API calls in order to record CPU data:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;os&amp;quot;&#xA;    &amp;quot;runtime/pprof&amp;quot;&#xA;)&#xA;&#xA;// bigBytes allocates 10 sets of 100 megabytes&#xA;func bigBytes() *[]byte {&#xA;    s := make([]byte, 100000000)&#xA;    return &amp;amp;s&#xA;}&#xA;&#xA;func main() {&#xA;    pprof.StartCPUProfile(os.Stdout)&#xA;    defer pprof.StopCPUProfile()&#xA;&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we use &lt;code&gt;os.Stdout&lt;/code&gt; to make the example easier (i.e. no need to create a file)&#xA;We’ll just use the shell’s ability to redirect output to create the profile file instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can then build and run the application and save the profile data to a file:&lt;br&gt;&#xA;&lt;code&gt;go build -o app &amp;amp;&amp;amp; time ./app &amp;gt; cpu.profile&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally we can inspect the data interactively using go tool like so:&lt;br&gt;&#xA;&lt;code&gt;go tool pprof cpu.profile&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here you’ll see an interactive prompt has started up.&lt;br&gt;&#xA;So let’s execute the &lt;code&gt;top&lt;/code&gt; command and see what output we get:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(pprof) top&#xA;Showing nodes accounting for 180ms, 100% of 180ms total&#xA;      flat  flat%   sum%        cum   cum%&#xA;     180ms   100%   100%      180ms   100%  runtime.memclrNoHeapPointers /.../src/runtime/memclr_amd64.s&#xA;         0     0%   100%      180ms   100%  main.bigBytes /.../code/go/profiling/main.go (inline)&#xA;         0     0%   100%      180ms   100%  main.main /.../code/go/profiling/main.go&#xA;         0     0%   100%      180ms   100%  runtime.(*mheap).alloc /.../src/runtime/mheap.go&#xA;         0     0%   100%      180ms   100%  runtime.largeAlloc /.../src/runtime/malloc.go&#xA;         0     0%   100%      180ms   100%  runtime.main /.../src/runtime/proc.go&#xA;         0     0%   100%      180ms   100%  runtime.makeslice /.../src/runtime/slice.go&#xA;         0     0%   100%      180ms   100%  runtime.mallocgc /.../src/runtime/malloc.go&#xA;         0     0%   100%      180ms   100%  runtime.mallocgc.func1 /.../src/runtime/malloc.go&#xA;         0     0%   100%      180ms   100%  runtime.systemstack /.../src/runtime/asm_amd64.s&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So this suggests the biggest CPU consumer is &lt;code&gt;runtime.memclrNoHeapPointers&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let’s now view a “line by line” breakdown to see if we can pinpoint the CPU usage further.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We’ll do this by using the &lt;code&gt;list &amp;lt;function regex&amp;gt;&lt;/code&gt; command.&lt;br&gt;&#xA;We can see from the &lt;code&gt;top&lt;/code&gt; command that our &lt;code&gt;main&lt;/code&gt; function is available via &lt;code&gt;main.main&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let’s list any functions within the &lt;code&gt;main&lt;/code&gt; namespace:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(pprof) list main\.&#xA;Total: 180ms&#xA;ROUTINE ======================== main.bigBytes in /.../go/profiling/main.go&#xA;         0      180ms (flat, cum)   100% of Total&#xA;         .          .      6:   &amp;quot;runtime/pprof&amp;quot;&#xA;         .          .      7:)&#xA;         .          .      8:&#xA;         .          .      9:// bigBytes allocates 10 sets of 100 megabytes&#xA;         .          .     10:func bigBytes() *[]byte {&#xA;         .      180ms     11:   s := make([]byte, 100000000)&#xA;         .          .     12:   return &amp;amp;s&#xA;         .          .     13:}&#xA;         .          .     14:&#xA;         .          .     15:func main() {&#xA;         .          .     16:   pprof.StartCPUProfile(os.Stdout)&#xA;ROUTINE ======================== main.main in /.../code/go/profiling/main.go&#xA;         0      180ms (flat, cum)   100% of Total&#xA;         .          .     15:func main() {&#xA;         .          .     16:   pprof.StartCPUProfile(os.Stdout)&#xA;         .          .     17:   defer pprof.StopCPUProfile()&#xA;         .          .     18:&#xA;         .          .     19:   for i := 0; i &amp;lt; 10; i++ {&#xA;         .      180ms     20:           s := bigBytes()&#xA;         .          .     21:           if s == nil {&#xA;         .          .     22:                   log.Println(&amp;quot;oh noes&amp;quot;)&#xA;         .          .     23:           }&#xA;         .          .     24:   }&#xA;         .          .     25:}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so yes we can see that 180ms is spent in the &lt;code&gt;bigBytes&lt;/code&gt; function and pretty much all of &lt;em&gt;that&lt;/em&gt; function’s time is spent allocating memory via &lt;code&gt;make([]byte, 100000000)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;memory-analysis&#34;&gt;Memory Analysis&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Before we move on, let’s look at how to profile our memory consumption.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this we’ll change our application slightly so that &lt;code&gt;StartCPUProfile&lt;/code&gt; becomes &lt;code&gt;WriteHeapProfile&lt;/code&gt; (we’ll also move this call to the bottom of our &lt;code&gt;main&lt;/code&gt; function otherwise if we keep it at the top of the function no memory has been allocated at that point). We’ll also remove the &lt;code&gt;StopCPUProfile&lt;/code&gt; call altogether (as recording the heap is done as a &lt;em&gt;snapshot&lt;/em&gt; rather than an ongoing process like with the CPU profiling):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;os&amp;quot;&#xA;    &amp;quot;runtime/pprof&amp;quot;&#xA;)&#xA;&#xA;// bigBytes allocates 10 sets of 100 megabytes&#xA;func bigBytes() *[]byte {&#xA;    s := make([]byte, 100000000)&#xA;    return &amp;amp;s&#xA;}&#xA;&#xA;func main() {&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;&#xA;    pprof.WriteHeapProfile(os.Stdout)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, we’ll build and execute the application and redirect the stdout to a file (for simplicity), but you could have created the file dynamically within your application if you so choose:&lt;br&gt;&#xA;&lt;code&gt;go build -o app &amp;amp;&amp;amp; time ./app &amp;gt; memory.profile&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point we can now run pprof to interactively inspect the memory profile data:&lt;br&gt;&#xA;&lt;code&gt;go tool pprof memory.profile&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let’s run the top command and see what the output is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(pprof) top&#xA;Showing nodes accounting for 95.38MB, 100% of 95.38MB total&#xA;      flat  flat%   sum%        cum   cum%&#xA;   95.38MB   100%   100%    95.38MB   100%  main.bigBytes /...ain.go (inline)&#xA;         0     0%   100%    95.38MB   100%  main.main /.../profiling/main.go&#xA;         0     0%   100%    95.38MB   100%  runtime.main /.../runtime/proc.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For a simple example application like we’re using, this is fine as it indicates pretty clearly which function is responsible for the majority of the memory allocation (&lt;code&gt;main.bigBytes&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if I wanted a more specific breakdown of the data I would execute &lt;code&gt;list main.&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(pprof) list main.&#xA;Total: 95.38MB&#xA;ROUTINE ======================== main.bigBytes in /.../go/profiling/main.go&#xA;   95.38MB    95.38MB (flat, cum)   100% of Total&#xA;         .          .      6:   &amp;quot;runtime/pprof&amp;quot;&#xA;         .          .      7:)&#xA;         .          .      8:&#xA;         .          .      9:// bigBytes allocates 10 sets of 100 megabytes&#xA;         .          .     10:func bigBytes() *[]byte {&#xA;   95.38MB    95.38MB     11:   s := make([]byte, 100000000)&#xA;         .          .     12:   return &amp;amp;s&#xA;         .          .     13:}&#xA;         .          .     14:&#xA;         .          .     15:func main() {&#xA;         .          .     16:   for i := 0; i &amp;lt; 10; i++ {&#xA;ROUTINE ======================== main.main in /.../code/go/profiling/main.go&#xA;         0    95.38MB (flat, cum)   100% of Total&#xA;         .          .     12:   return &amp;amp;s&#xA;         .          .     13:}&#xA;         .          .     14:&#xA;         .          .     15:func main() {&#xA;         .          .     16:   for i := 0; i &amp;lt; 10; i++ {&#xA;         .    95.38MB     17:           s := bigBytes()&#xA;         .          .     18:           if s == nil {&#xA;         .          .     19:                   log.Println(&amp;quot;oh noes&amp;quot;)&#xA;         .          .     20:           }&#xA;         .          .     21:   }&#xA;         .          .     22:&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This indicates where all our memory is allocated on a “line-by-line” basis.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;remotely-analyse-via-web-server&#34;&gt;Remotely analyse via web server&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the following example we’ve modified the application to start up a web server and we’ve imported the &lt;code&gt;&amp;quot;net/http/pprof&amp;quot;&lt;/code&gt; &lt;a href=&#34;https://golang.org/pkg/net/http/pprof/&#34; target=&#34;_blank&#34;&gt;package&lt;/a&gt; which automatically profiles what’s happening.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if your application already uses a web server, then you don’t need to start another. The pprof package will hook into your web server’s multiplexer.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;log&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    _ &amp;quot;net/http/pprof&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;// bigBytes allocates 10 sets of 100 megabytes&#xA;func bigBytes() *[]byte {&#xA;    s := make([]byte, 100000000)&#xA;    return &amp;amp;s&#xA;}&#xA;&#xA;func main() {&#xA;    var wg sync.WaitGroup&#xA;&#xA;    go func() {&#xA;        log.Println(http.ListenAndServe(&amp;quot;localhost:6060&amp;quot;, nil))&#xA;    }()&#xA;&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;&#xA;    wg.Add(1)&#xA;    wg.Wait() // this is for the benefit of the pprof server analysis&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When you build and run this binary, first visit the web server the code is running.&lt;br&gt;&#xA;You’ll find that the pprof data is accessible via the path &lt;code&gt;/debug/pprof/&lt;/code&gt;:&lt;br&gt;&#xA;&lt;code&gt;http://localhost:6060/debug/pprof/&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should see something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;profiles:&#xA;0    block&#xA;4    goroutine&#xA;5    heap&#xA;0    mutex&#xA;7    threadcreate&#xA;&#xA;full goroutine stack dump&#xA;&#xA;/debug/pprof/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where block, goroutine, heap, mutex and threadcreate are all links off to the recorded data; and by ‘recorded data’ I mean they each link through to a different &lt;code&gt;.profile&lt;/code&gt;. This isn’t particularly useful though. A tool is needed to process these &lt;code&gt;.profile&lt;/code&gt; data files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We’ll come back to that in a moment, first let’s understand what these five profiles represent:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;block&lt;/strong&gt;: stack traces that led to blocking on synchronization primitives&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;goroutine&lt;/strong&gt;: stack traces of all current goroutines&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;heap&lt;/strong&gt;: a sampling of all heap allocations&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;mutex&lt;/strong&gt;: stack traces of holders of contended mutexes&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;threadcreate&lt;/strong&gt;: stack traces that led to the creation of new OS threads&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The web server can also generate a 30 second CPU profile, which you can access via &lt;a href=&#34;http://localhost:6060/debug/pprof/profile&#34; target=&#34;_blank&#34;&gt;http://localhost:6060/debug/pprof/profile&lt;/a&gt; (it won’t be viewable in the browser, instead it’ll be downloaded to your file system).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The CPU profile endpoint is not listed when viewing &lt;code&gt;/debug/pprof/&lt;/code&gt; simply because the CPU profile has a special API, the &lt;code&gt;StartCPUProfile&lt;/code&gt; and &lt;code&gt;StopCPUProfile&lt;/code&gt; functions that stream output to a writer during profiling, hence this hidden endpoint will ultimately download the results to your file system (we looked at how to use this API in the previous section).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The web server can also generate a “trace” file, which you can access via &lt;a href=&#34;http://localhost:6060/debug/pprof/trace?seconds=5&#34; target=&#34;_blank&#34;&gt;http://localhost:6060/debug/pprof/trace?seconds=5&lt;/a&gt; (again, it’s not listed for similar reasons as the CPU profile - in that it generates file output that is downloaded to your file system). This trace file out requires the use of &lt;code&gt;go tool trace&lt;/code&gt; (which we’ll cover in the next section).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;more info on pprof options can be found here: &lt;a href=&#34;https://golang.org/pkg/net/http/pprof/&#34; target=&#34;_blank&#34;&gt;golang.org/pkg/net/http/pprof/&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re using a custom URL router, you&amp;rsquo;ll need to register the individual &lt;code&gt;pprof&lt;/code&gt; endpoints:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/pprof&amp;quot;&#xA;)&#xA;&#xA;func message(w http.ResponseWriter, r *http.Request) {&#xA;    w.Write([]byte(&amp;quot;Hello World&amp;quot;))&#xA;}&#xA;&#xA;func main() {&#xA;    r := http.NewServeMux()&#xA;    r.HandleFunc(&amp;quot;/&amp;quot;, message)&#xA;&#xA;    r.HandleFunc(&amp;quot;/debug/pprof/&amp;quot;, pprof.Index)&#xA;    r.HandleFunc(&amp;quot;/debug/pprof/cmdline&amp;quot;, pprof.Cmdline)&#xA;    r.HandleFunc(&amp;quot;/debug/pprof/profile&amp;quot;, pprof.Profile)&#xA;    r.HandleFunc(&amp;quot;/debug/pprof/symbol&amp;quot;, pprof.Symbol)&#xA;    r.HandleFunc(&amp;quot;/debug/pprof/trace&amp;quot;, pprof.Trace)&#xA;&#xA;    http.ListenAndServe(&amp;quot;:8080&amp;quot;, r)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;So ideally you would use &lt;code&gt;go tool pprof&lt;/code&gt; on the command line.&lt;br&gt;&#xA;As this allows you to more easily interpret and interrogate the data interactively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this, you have to run your binary as before and then, in a &lt;em&gt;separate&lt;/em&gt; shell, execute:&lt;br&gt;&#xA;&lt;code&gt;go tool pprof http://localhost:6060/debug/pprof/&amp;lt;.profile&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, let’s look at the memory heap profile data:&lt;br&gt;&#xA;&lt;code&gt;go tool pprof http://localhost:6060/debug/pprof/heap&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here you’ll see an interactive prompt has started up:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap&#xA;Saved profile in /.../pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.005.pb.gz&#xA;Type: inuse_space&#xA;Time: Oct 27, 2017 at 10:01am (BST)&#xA;Entering interactive mode (type &amp;quot;help&amp;quot; for commands, &amp;quot;o&amp;quot; for options)&#xA;(pprof)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you’ll see the “type” is set to &lt;code&gt;inuse_space&lt;/code&gt; (meaning how much memory is still in use)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;As shown, you can type either &lt;code&gt;help&lt;/code&gt; or &lt;code&gt;o&lt;/code&gt; to see what’s available to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are a couple of useful commands:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;top&lt;/code&gt;: outputs top entries in text form&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;topK&lt;/code&gt;: where K is a number (e.g. top2 would show top two entries)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;list &amp;lt;function regex&amp;gt;&lt;/code&gt;: outputs top entries in text form&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For example, if I execute &lt;code&gt;top&lt;/code&gt; then we’d see the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Showing nodes accounting for 95.38MB, 100% of 95.38MB total&#xA;      flat  flat%   sum%        cum   cum%&#xA;   95.38MB   100%   100%    95.38MB   100%  main.bigBytes /...ain.go (inline)&#xA;         0     0%   100%    95.38MB   100%  main.main /.../profiling/main.go&#xA;         0     0%   100%    95.38MB   100%  runtime.main /.../runtime/proc.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For a simple example application like we’re using, this is fine as it indicates pretty clearly which function is responsible for the majority of the memory allocation (&lt;code&gt;main.bigBytes&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if I wanted a more specific breakdown of the data I would execute list &lt;code&gt;main.main&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Total: 95.38MB&#xA;ROUTINE ======================== main.main in /.../profiling/main.go&#xA;   95.38MB    95.38MB (flat, cum)   100% of Total&#xA;         .          .      8:   &amp;quot;sync&amp;quot;&#xA;         .          .      9:)&#xA;         .          .     10:&#xA;         .          .     11:// bigBytes allocates 10 sets of 100 megabytes&#xA;         .          .     12:func bigBytes() *[]byte {&#xA;   95.38MB    95.38MB     13:   s := make([]byte, 100000000)&#xA;         .          .     14:   return &amp;amp;s&#xA;         .          .     15:}&#xA;         .          .     16:&#xA;         .          .     17:func main() {&#xA;         .          .     18:   fmt.Println(&amp;quot;starting...&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This indicates where all our memory is allocated on a “line-by-line” basis.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I noted earlier that the default “type” for the heap analysis was “memory still in use”. But there is an alternative type which indicates the amount of memory that was allocated in total throughout the lifetime of the program. You can switch to that mode using the &lt;code&gt;-alloc_space&lt;/code&gt; flag like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go tool pprof -alloc_space http://localhost:6060/debug/pprof/heap&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let’s see the difference in the output by executing the &lt;code&gt;list&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(pprof) list main.bigBytes&#xA;&#xA;Total: 954.63MB&#xA;ROUTINE ======================== main.bigBytes in /.../go/profiling/main.go&#xA;  953.75MB   953.75MB (flat, cum) 99.91% of Total&#xA;         .          .      7:   &amp;quot;sync&amp;quot;&#xA;         .          .      8:)&#xA;         .          .      9:&#xA;         .          .     10:// bigBytes allocates 10 sets of 100 megabytes&#xA;         .          .     11:func bigBytes() *[]byte {&#xA;  953.75MB   953.75MB     12:   s := make([]byte, 100000000)&#xA;         .          .     13:   return &amp;amp;s&#xA;         .          .     14:}&#xA;         .          .     15:&#xA;         .          .     16:func main() {&#xA;         .          .     17:   var wg sync.WaitGroup&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you wanted to be explicit you could have used the “in use” type like so:&lt;br&gt;&#xA;&lt;code&gt;go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason to choose either &lt;code&gt;-inuse_space&lt;/code&gt; or &lt;code&gt;-alloc_space&lt;/code&gt; will depend on where your specific concerns are focused. For example, if you’re concerned about garbage collection performance then you’ll want to look at the “allocated” memory (i.e. &lt;code&gt;-alloc_space&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can also inspect the number of objects (not just their space) with &lt;code&gt;-inuse_objects&lt;/code&gt; and &lt;code&gt;-alloc_objects&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;image-generation&#34;&gt;Image Generation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can also generate an image of your analysis data using either the flag &lt;code&gt;-png&lt;/code&gt;, &lt;code&gt;-gif&lt;/code&gt; or &lt;code&gt;-svg&lt;/code&gt; and then redirecting stdout to a filename like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;go tool pprof -png http://localhost:6060/debug/pprof/heap &amp;gt; data.png&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This generates an image that looks like the following (notice how the bigger the box, the more resources it’s consuming - this helps you ‘at a glance’ to identify a potential problem zone):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/profiling_go.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/profiling_go.png&#34; alt=&#34;profiling go&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can also output as a PDF with &lt;code&gt;-pdf&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;web-ui&#34;&gt;Web UI&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Finally, there is a interactive web ui coming for pprof in the near future (as of November 2017).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See &lt;a href=&#34;https://rakyll.org/pprof-ui/&#34; target=&#34;_blank&#34;&gt;this post&lt;/a&gt; for more details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in short you can get the updated pprof tool from GitHub and then execute it with the new flag &lt;code&gt;-http&lt;/code&gt; (e.g. &lt;code&gt;-http=:8080&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;trace&#34;&gt;Trace&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://golang.org/cmd/trace/&#34; target=&#34;_blank&#34;&gt;Trace&lt;/a&gt; is a tool for visualization and analysis of trace data.&lt;br&gt;&#xA;It’s suited at finding out what your program is doing over time, not in aggregate.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want to track down slow functions, or generally find where your program is spending most of its CPU time, then you should consider using &lt;code&gt;go tool pprof&lt;/code&gt; instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let’s first modify our application to utilise tracing…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func main() {&#xA;    trace.Start(os.Stdout)&#xA;    defer trace.Stop()&#xA;&#xA;    for i := 0; i &amp;lt; 10; i++ {&#xA;        s := bigBytes()&#xA;        if s == nil {&#xA;            log.Println(&amp;quot;oh noes&amp;quot;)&#xA;        }&#xA;    }&#xA;&#xA;    var wg sync.WaitGroup&#xA;    wg.Add(1)&#xA;&#xA;    var result []byte&#xA;    go func() {&#xA;        result = make([]byte, 500000000)&#xA;        log.Println(&amp;quot;done here&amp;quot;)&#xA;        wg.Done()&#xA;    }()&#xA;&#xA;    wg.Wait()&#xA;    log.Printf(&amp;quot;%T&amp;quot;, result)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So, as far as utilising tracing, all we’ve done is import &lt;code&gt;&amp;quot;runtime/trace&amp;quot;&lt;/code&gt; and then added calls to the &lt;code&gt;trace.Start&lt;/code&gt; and &lt;code&gt;trace.Stop&lt;/code&gt; functions (we &lt;code&gt;defer&lt;/code&gt; the &lt;code&gt;trace.Stop&lt;/code&gt; in order to ensure we trace everything our application is doing).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally we create a goroutine and allocate a large 500mb slice of bytes. We wait for the goroutine to complete and then we log the type of the result. We’re doing this just so we have some additional spike data to visualise.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now let’s re-compile our application, generate the trace data and open it with the trace tool…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ go build -o app&#xA;$ time ./app &amp;gt; app.trace&#xA;$ go tool trace app.trace&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can also generate a pprof compatible file from a trace by using the &lt;code&gt;-pprof&lt;/code&gt; flag (if you decided you wanted to dynamically inspect the data that way). See the &lt;a href=&#34;https://golang.org/cmd/trace/&#34; target=&#34;_blank&#34;&gt;go documentation&lt;/a&gt; for more details.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here’s the output from running &lt;code&gt;go tool trace app.trace&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;2017/10/29 09:30:40 Parsing trace...&#xA;2017/10/29 09:30:40 Serializing trace...&#xA;2017/10/29 09:30:40 Splitting trace...&#xA;2017/10/29 09:30:40 Opening browser&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You’ll now see your default web browser should have automatically opened to:&lt;br&gt;&#xA;&lt;a href=&#34;http://127.0.0.1:60331/&#34; target=&#34;_blank&#34;&gt;http://127.0.0.1:60331&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it’s best to use Chrome, as &lt;code&gt;go tool trace&lt;/code&gt; is designed to work best with it.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The page that is loaded will show the following list of links:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;View trace&lt;/li&gt;&#xA;&lt;li&gt;Goroutine analysis&lt;/li&gt;&#xA;&lt;li&gt;Network blocking profile&lt;/li&gt;&#xA;&lt;li&gt;Synchronization blocking profile&lt;/li&gt;&#xA;&lt;li&gt;Syscall blocking profile&lt;/li&gt;&#xA;&lt;li&gt;Scheduler latency profile&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Each of these items can give a good insight as to what your application is doing, but we’re most interested in the first one “view trace”. Click it and it’ll give you a complete overview of what your application is doing in an interactive graph.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/profiling_go_2.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/profiling_go_2.png&#34; alt=&#34;profiling go 2&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;press &lt;code&gt;&amp;lt;Shift-?&amp;gt;&lt;/code&gt; to show shortcut keys, like &lt;code&gt;w&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt; for zooming in/out.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;goroutines&#34;&gt;Goroutines&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you zoom in enough on the graph you’ll see the “goroutines” segment is made up of two colours: a light green (runnable goroutines) and a dark green (running goroutines). If you click on that part of the graph you’ll see the details of that sample in the bottom preview of the screen. It’s interesting to see how, at any given moment, there can be multiple goroutines but not all of them are necessarily running all at once.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in our example you see the program moves between having one goroutine ready to run, but not actually running (e.g. it’s “runnable”) and then we move towards two goroutines running (e.g. they’re both “running” and so there are no goroutines left marked as “runnable”).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s also interesting to see the correlation between the number of goroutines running and the number of &lt;em&gt;actual&lt;/em&gt; underlying OS threads being utilised (i.e. the number of threads the goroutines are being scheduled on to).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;threads&#34;&gt;Threads&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Again, if you zoom in enough on the graph you’ll see the “threads” segment is made up of two colours: a light purple (syscalls) and a dark purple (running threads).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What’s interesting about the “heap” segment of the UI is that we can see for a short while we never allocate more (total) than 100mb to the heap because the go garbage collection is running concurrently (we can see it running on various processes/threads) and is clearing up after us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This makes sense because in our code we allocate 100mb of memory and then assign it to a variable &lt;code&gt;s&lt;/code&gt; which is scoped to exist only within the &lt;code&gt;for&lt;/code&gt; loop block. Once that loop iteration ends the &lt;code&gt;s&lt;/code&gt; value isn’t referenced anywhere else so the GC knows it can clean up that memory.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;heap&#34;&gt;Heap&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We can see as the program moves on that we eventually start seeing some contention and so the total allocated heap becomes 200mb then back and forth between 100mb and 200mb (this is because the GC isn’t running all the time). Then near the end we see the 500mb spike that I added to our code as the total allocated amount of memory in the heap shoots to 600mb.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But at that point, if we click on the spike in heap allocation, we can see in the bottom preview window the “NextGC” run indicates that the total allocated should be zero (which makes sense as that’s the end of the program).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;procs&#34;&gt;Procs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the “procs” section of the UI we can see during our large 500mb allocation that Proc 3 has a new goroutine running &lt;code&gt;main.main.func1&lt;/code&gt; (which is our go function that’s doing the allocating).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you were to “View Options” and then tick “Flow events” you’ll see an arrow from the &lt;code&gt;main.main&lt;/code&gt; function going towards the &lt;code&gt;main.main.func1&lt;/code&gt; function running on a separate process/thread (probably a bit difficult to see in the below image, but it’s definitely there).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/profiling_go_3.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/profiling_go_3.png&#34; alt=&#34;profiling go 3&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So it’s good to be able to visually see the correlation between first of all the &lt;code&gt;main.main.func1&lt;/code&gt; goroutine running and the memory allocation occurring at that time, but also being able to see the cause and effect (i.e. the &lt;em&gt;flow&lt;/em&gt;) of the program (i.e. knowing &lt;em&gt;what&lt;/em&gt; exactly triggered the new goroutine to be spun up).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s our tour of various tools for profiling your Go code. Take a look at my earlier article on profiling Python for more of the same.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/profiling-go/</guid>
      <link>https://www.integralist.co.uk/posts/profiling-go/</link>
      <pubDate>Tue, 31 Oct 2017 00:00:00 +0000</pubDate>
      <title>Profiling Go</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;re a software engineer with a new laptop.&lt;br&gt;&#xA;You&amp;rsquo;re going to be writing code in multiple languages.&lt;br&gt;&#xA;You&amp;rsquo;re going to have projects of varying dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you want to avoid the issues you&amp;rsquo;ve had in the past:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Messy installations of lots of different software packages.&lt;/li&gt;&#xA;&lt;li&gt;Clogging up your system with programming language version managers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You decide to use &lt;a href=&#34;https://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt;.&lt;br&gt;&#xA;It&amp;rsquo;s a dependency sure, but you&amp;rsquo;ve got to install &lt;em&gt;something&lt;/em&gt;!&lt;br&gt;&#xA;With Docker it allows your environment to stay clean.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s see two simple examples:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.python.org/&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I don&amp;rsquo;t claim this to be &amp;lsquo;the way&amp;rsquo; to do this.&lt;br&gt;&#xA;This is just a setup that works well enough for me.&lt;br&gt;&#xA;I&amp;rsquo;m also a Vim user, so your mileage may vary.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;python&#34;&gt;Python&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You have a Python project you need to work on.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I won&amp;rsquo;t explain how Python works,&lt;br&gt;&#xA;I&amp;rsquo;ll just presume you&amp;rsquo;re a Pythonista&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the folder structure we&amp;rsquo;re dealing with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo-project/&#xA;| Dockerfile&#xA;| Makefile&#xA;| app.py&#xA;| requirements.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We have a Dockerfile (naturally), along with a Makefile to allow us to more easily build our docker image. We also have an application script + a set of dependencies. Nice and simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here&amp;rsquo;s what the Dockerfile looks like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM python:3.6.1&#xA;&#xA;WORKDIR /tmp&#xA;&#xA;RUN apt-get update -y&#xA;RUN apt-get install -y git ncurses-dev&#xA;RUN git clone https://github.com/vim/vim.git &amp;amp;&amp;amp; cd vim &amp;amp;&amp;amp; ./configure --enable-python3interp=yes &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install&#xA;&#xA;ADD ./requirements.txt /app/requirements.txt&#xA;RUN pip install -r /app/requirements.txt&#xA;&#xA;COPY .vim /root/.vim&#xA;COPY .vimrc /root/.vimrc&#xA;&#xA;WORKDIR /app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see we&amp;rsquo;re building our Docker image from an official Python base image (at the time of writing it&amp;rsquo;s the latest Python version).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We jump into a tmp directory so that we can install some dependencies required to get our setup just how we want it. So this means installing &lt;code&gt;git&lt;/code&gt; so we can clone down the latest build of Vim and we also install &lt;code&gt;ncurses-dev&lt;/code&gt; which is necessary in order to compile Vim.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After that we copy our &lt;code&gt;requirements.txt&lt;/code&gt; file into the image and install the packages specified inside that file. We also add in our &lt;code&gt;.vim&lt;/code&gt; directory and &lt;code&gt;.vimrc&lt;/code&gt; file to the image.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the Makefile has a command for copying &lt;code&gt;.vim/.vimrc&lt;/code&gt; into the current project directory, as &lt;code&gt;docker build&lt;/code&gt; has a specific context environment that is effectively the location of the Dockerfile&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next we have the Makefile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;copy_vim_files:&#xA;        @if [ ! -d &amp;quot;./.vim&amp;quot; ]; then cp -r &amp;quot;$$HOME/.vim&amp;quot; ./.vim; fi&#xA;        @if [ ! -f &amp;quot;./.vimrc&amp;quot; ]; then cp &amp;quot;$$HOME/.vimrc&amp;quot; ./.vimrc; fi&#xA;&#xA;remove_vim_files:&#xA;        @rm -rf ./.vim&#xA;        @rm ./.vimrc&#xA;&#xA;build: copy_vim_files&#xA;        @docker build -t python-container-with-vim .&#xA;&#xA;run: build&#xA;        @docker run -it -v &amp;quot;$$(pwd)&amp;quot;:/app python-container-with-vim /bin/bash&#xA;&#xA;clean: remove_vim_files&#xA;        -@docker rmi -f python-container-with-vim &amp;amp;&amp;gt; /dev/null || true&#xA;&#xA;rebuild: clean run&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s lots going on in there, but the important thing to know is that to start up your docker container (with Python and Vim pre-installed) is to use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;make run&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will copy over the host &lt;code&gt;.vim/.vimrc&lt;/code&gt; directory/files, then build a new image and then call &lt;code&gt;docker run ...&lt;/code&gt; where it&amp;rsquo;ll mount the project directory as a volume into the running container.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you&amp;rsquo;re inside the container just execute &lt;code&gt;vim app.py&lt;/code&gt; and off you go writing code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Just for completion, here is our application script:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;print(&#39;hi&#39;)&#xA;food = &amp;quot;is a thing&amp;quot;  # if linting is installed properly this will error&#xA;&#xA;&#xA;def hello(message):&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    My summary line starts capitalized and ends with a period.&#xA;&#xA;    my bigger description is going here&#xA;    so pay attention to what it says&#xA;    &amp;quot;&amp;quot;&amp;quot;&#xA;    print(message)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above script has some &amp;lsquo;linting&amp;rsquo; issues, so if our packages (see below) are installed correctly then we should see Vim highlight the issue to us.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;flake8==3.2.1&#xA;flake8-deprecated==1.1&#xA;flake8-docstrings==1.0.3&#xA;flake8-mock==0.3&#xA;flake8-quotes==0.9.0&#xA;mypy==0.501&#xA;pep8-naming==0.4.1&#xA;pylint==1.6.4&#xA;pytest==3.0.5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the &lt;code&gt;requirements.txt&lt;/code&gt; file that we&amp;rsquo;ve installed a few different linters along with the MyPy static analysis tool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it really. You can reuse the Dockerfile and Makefile for all your projects as they don&amp;rsquo;t do anything specific to this project. Just setup the docker image/container so you can execute &lt;code&gt;make run&lt;/code&gt; and start developing.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;go&#34;&gt;Go&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You have a Go project you need to work on.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I won&amp;rsquo;t explain how Go works,&lt;br&gt;&#xA;I&amp;rsquo;ll just presume you&amp;rsquo;re a Gopher&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the folder structure we&amp;rsquo;re dealing with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bar-project/&#xA;| Dockerfile&#xA;| Dockerfile-compile&#xA;| Godeps&#xA;| Makefile&#xA;| app.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So here&amp;rsquo;s our main Dockerfile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM golang:1.8&#xA;&#xA;RUN apt-get update -y&#xA;RUN apt-get install -y wget git ncurses-dev time&#xA;&#xA;WORKDIR /tmp&#xA;RUN git clone https://github.com/vim/vim.git &amp;amp;&amp;amp; cd vim &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install&#xA;&#xA;WORKDIR /go/src&#xA;COPY .vim /root/.vim&#xA;COPY .vimrc /root/.vimrc&#xA;COPY ./Godeps /go/src&#xA;&#xA;RUN wget https://raw.githubusercontent.com/pote/gpm/v1.4.0/bin/gpm &amp;amp;&amp;amp; chmod +x gpm &amp;amp;&amp;amp; mv gpm /usr/local/bin&#xA;RUN gpm install&#xA;RUN cp -r ./github.com /github.com  # backup packages to root to prevent volume mount removing it&#xA;&#xA;# Install Go binaries that are utilised by the vim-go plugin:&#xA;# https://github.com/fatih/vim-go/blob/master/plugin/go.vim#L9&#xA;#&#xA;# We don&#39;t manually install them, we let vim-go handle that&#xA;# We use vim&#39;s `execute` command to pipe commands&#xA;# This helps avoid &amp;quot;Press ENTER or type command to continue&amp;quot;&#xA;RUN time vim -c &amp;quot;execute &#39;silent GoUpdateBinaries&#39; | execute &#39;quit&#39;&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again we&amp;rsquo;re not doing anything too crazy (not until the end, which I&amp;rsquo;ll explain). We&amp;rsquo;re building a new image from an official base image, then we&amp;rsquo;re installing dependencies that allow us to manually compile the Vim editor.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we copy over our vim files and the &lt;code&gt;Godeps&lt;/code&gt; dependencies file and we install our dependency manager &lt;a href=&#34;https://github.com/pote/gpm&#34; target=&#34;_blank&#34;&gt;gpm&lt;/a&gt; and install the packages we want to use within our application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we back up the installed depedencies (&lt;code&gt;./github.com&lt;/code&gt;) to another directory. The reason we do that is because when we mount our host project directory into the running container we will end up accidentally replacing the installed packages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally we run vim and pass it a script to be executed once Vim has loaded. What this does is allow the statically built image to include the updated set of depedencies that the &lt;a href=&#34;https://github.com/fatih/vim-go&#34; target=&#34;_blank&#34;&gt;vim-go&lt;/a&gt; plugin requires. I could have installed them manually, but then using the built in command provided by vim-go means I don&amp;rsquo;t have to ensure my list of go tools still matches up to what vim-go is using.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The downside to this is that when you build the image, you&amp;rsquo;ll see (for ~20-30 seconds) Vim started and you wont be able to interact with it at all during that time. This is because it&amp;rsquo;s installing the dependencies it uses. But after that, Vim will close and you&amp;rsquo;ll be placed at the containers shell prompt. From there you can run Vim and start coding.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the Go Makefile (it works similarly to the Python one):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bin := &amp;quot;/usr/local/bin/fastly&amp;quot;&#xA;vim_dir := &amp;quot;./.vim&amp;quot;&#xA;vimrc := &amp;quot;./.vimrc&amp;quot;&#xA;container_env := &amp;quot;go-container-with-vim&amp;quot;&#xA;container_compiler := &amp;quot;go-compiler&amp;quot;&#xA;&#xA;copy_vim_files:&#xA;  @if [ ! -d $(vim_dir) ]; then cp -r &amp;quot;$$HOME/.vim&amp;quot; $(vim_dir); fi&#xA;  @if [ ! -f $(vimrc) ]; then cp &amp;quot;$$HOME/.vimrc&amp;quot; $(vimrc); fi&#xA;&#xA;remove_vim_files:&#xA;  @rm -rf $(vim_dir) &amp;amp;&amp;gt; /dev/null || true&#xA;  @rm $(vimrc) &amp;amp;&amp;gt; /dev/null || true&#xA;&#xA;remove_compiled_files:&#xA;  @rm ./fastly.{darwin,linux,windows.exe} &amp;amp;&amp;gt; /dev/null || true&#xA;&#xA;clean: remove_vim_files remove_compiled_files&#xA;  @docker rmi -f $(container_env) &amp;amp;&amp;gt; /dev/null || true&#xA;  @docker rmi -f $(container_compiler) &amp;amp;&amp;gt; /dev/null || true&#xA;&#xA;uninstall: clean&#xA;  @rm $(bin) &amp;amp;&amp;gt; /dev/null || true&#xA;&#xA;build: copy_vim_files&#xA;  @docker build -t $(container_env) .&#xA;&#xA;dev: build remove_vim_files&#xA;  @docker run -it -v &amp;quot;$$(pwd)&amp;quot;:/go/src $(container_env) /bin/bash&#xA;&#xA;rebuild: clean run&#xA;&#xA;compile:&#xA;  @docker build -t $(container_compiler) -f ./Dockerfile-compile .&#xA;  @docker run -it -v &amp;quot;$$(pwd)&amp;quot;:/go/src $(container_compiler) || true&#xA;&#xA;copy_binary:&#xA;  cp ./fastly.darwin $(bin)&#xA;&#xA;install: compile copy_binary remove_compiled_files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One thing I did this time was change the &lt;code&gt;make run&lt;/code&gt; for &lt;code&gt;make dev&lt;/code&gt; as I feel that&amp;rsquo;s more indicative of what we&amp;rsquo;re doing (the &amp;lsquo;run&amp;rsquo; suggests we&amp;rsquo;re &lt;em&gt;running&lt;/em&gt; our application when we&amp;rsquo;re really just wanting to drop into a development environment).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s a few more steps in the Go Makefile and that&amp;rsquo;s just for the purposes of having a separate Dockerfile for compiling our application. The following is the other Dockerfile we have in our project:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM golang:1.8&#xA;&#xA;WORKDIR /go/src&#xA;COPY ./Godeps /go/src&#xA;COPY ./compile.sh /go/src&#xA;&#xA;RUN apt-get update &amp;amp;&amp;amp; apt-get install wget&#xA;RUN wget https://raw.githubusercontent.com/pote/gpm/v1.4.0/bin/gpm &amp;amp;&amp;amp; chmod +x gpm &amp;amp;&amp;amp; mv gpm /usr/local/bin&#xA;RUN gpm install&#xA;RUN cp -r ./github.com /github.com  # backup packages to root to prevent volume mount removing it&#xA;&#xA;CMD [&amp;quot;./compile.sh&amp;quot;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This Dockerfile does much the same thing: get dependency file, install those specified dependencies, then back them up to another directory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This time though, when the container is run we use a separate script as the &lt;code&gt;CMD&lt;/code&gt; value as our script was getting quite long (as you&amp;rsquo;ll see).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is the contents of &lt;code&gt;compile.sh&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;make sure you &lt;code&gt;chmod +x ./compile.sh&lt;/code&gt; from your host&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#!/bin/sh&#xA;&#xA;# copy packages back into our source code directory&#xA;cp -fr /github.com ./github.com&#xA;&#xA;# compile application for the major operating systems&#xA;gox -osarch=&#39;linux/amd64&#39; -osarch=&#39;darwin/amd64&#39; -osarch=&#39;windows/amd64&#39; -output=&#39;fastly.{{.OS}}&#39;&#xA;&#xA;# run the relevant compatible compiled binary for this container&#39;s OS&#xA;./fastly.linux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The tasks we run are:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;copy the backed up dependencies back into the mounted project directory&lt;/li&gt;&#xA;&lt;li&gt;build the app using the default compiler for the OS †&lt;/li&gt;&#xA;&lt;li&gt;execute the compiled binary to show it can run correctly inside the container&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this means our compiled binary will be a linux based binary, so you can&amp;rsquo;t run it on your host machine if it&amp;rsquo;s not linux based (e.g. I&amp;rsquo;m using macOS). You&amp;rsquo;ll see that to allow me to compiled my application for multiple OS&amp;rsquo;s I&amp;rsquo;ve installed &lt;a href=&#34;https://github.com/mitchellh/gox&#34; target=&#34;_blank&#34;&gt;Gox&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now here is our Go application, it simply uses the logging dependency we&amp;rsquo;ve installed and that&amp;rsquo;s it. Nothing too fancy necessary for this example.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;&#xA;  log &amp;quot;github.com/Sirupsen/logrus&amp;quot;&#xA;)&#xA;&#xA;func init() {&#xA;  log.SetLevel(log.DebugLevel) // otherwise would not be shown&#xA;}&#xA;&#xA;func main() {&#xA;  fmt.Println(&amp;quot;Hello World!&amp;quot;)&#xA;&#xA;  logger := log.WithFields(log.Fields{&#xA;    &amp;quot;name&amp;quot;: &amp;quot;hello-world-app&amp;quot;,&#xA;  })&#xA;  logger.Debug(&amp;quot;this is my debug log message&amp;quot;)&#xA;  logger.Info(&amp;quot;this is my info log message&amp;quot;)&#xA;  logger.Warn(&amp;quot;this is my warn log message&amp;quot;)&#xA;  logger.Error(&amp;quot;this is my error log message&amp;quot;)&#xA;  logger.Fatal(&amp;quot;this is my Fatal log message&amp;quot;)&#xA;  logger.Panic(&amp;quot;this is my Panic log message&amp;quot;) // we don&#39;t actually reach here&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is our dependency file&amp;rsquo;s content, where we can see the &lt;a href=&#34;https://github.com/sirupsen/logrus&#34; target=&#34;_blank&#34;&gt;Logrus&lt;/a&gt; dependency we&amp;rsquo;ve specified (as well as Gox for the purposes of our container responsible for compiling our application for multiple OS&amp;rsquo;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;github.com/mitchellh/gox c9740af9c6574448fd48eb30a71f964014c7a837&#xA;github.com/sirupsen/logrus 10f801ebc38b33738c9d17d50860f484a0988ff5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;mounting-volumes&#34;&gt;Mounting Volumes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Just remember that when making changes inside the container, because you&amp;rsquo;ve mounted your host project directory as a volume, if you make a change or add a new file or compile something inside of the container; then it&amp;rsquo;ll be available on your host machine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is all fine, but you might want to look at setting up a &lt;code&gt;.gitignore&lt;/code&gt; file to ensure you don&amp;rsquo;t accidentally commit any unwanted items into your git repository.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/dev-environments-within-docker-containers/</guid>
      <link>https://www.integralist.co.uk/posts/dev-environments-within-docker-containers/</link>
      <pubDate>Wed, 29 Mar 2017 00:00:00 +0000</pubDate>
      <title>Dev Environments Within Docker Containers</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Just a quick post to cover the key architecture I&amp;rsquo;m using currently. I&amp;rsquo;m very interested to know how others are doing things in the hope that I can improve the security of my setup.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not a security paranoia nut, so I&amp;rsquo;m not looking for the most concrete solution. But definitely want to be sure I&amp;rsquo;m not missing anything obvious either&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;visual&#34;&gt;Visual&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is a high-level view of what I have currently:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/key-architecture.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/key-architecture.png&#34; alt=&#34;key architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;breakdown&#34;&gt;Breakdown&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s start at the top&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;laptop&#34;&gt;Laptop&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The laptop is password protected and the hard drive is automatically encrypted&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;password-data-store&#34;&gt;Password Data Store&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The laptop contains a password data store consisting of GPG keys for every record in the data store.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to access the data store (or any of its records), you need a private GPG key.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The data store is backed up to a private online git repository.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;private-gpg-key&#34;&gt;Private GPG Key&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The private key is itself protected by a secure passphrase (i.e. one that is almost impossible to crack - by today&amp;rsquo;s standards and recommendations - and I&amp;rsquo;ve not written it down but memorised it entirely).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The private/public key pair is stored on the laptop, but as the key is protected by a secure passphrase I feel (without going &lt;em&gt;over the top&lt;/em&gt; on security) this is as good as I&amp;rsquo;m probably going to get with it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The private key is also backed up onto a remote USB drive in case I lose my laptop and I need the key in order to access the data in the password data store.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;private-git-repository&#34;&gt;Private Git Repository&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The private git repo has two routes of access. The account itself with the relevant service provider and an SSH key that exists on my laptop to allow it to gain access to the contents of the repository (but not the contents of the files in the data store itself as they are protected by my private GPG key).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The passphrase for both the account and the SSH key are secure (by today&amp;rsquo;s standards and recommendations) and are stored inside the password data store.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If my laptop was lost, then I&amp;rsquo;d need to rely on the service provider&amp;rsquo;s ability to reset my account password via email, where by I could then remove the existing SSH key and replace it with a new one.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I mention replacing the SSH key because I don&amp;rsquo;t back it up. I feel this SSH key doesn&amp;rsquo;t need to be a long lasting key (unlike my private GPG key which I intend to keep as safe as possible + the offline backup as a fallback).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;vulnerabilities&#34;&gt;Vulnerabilities?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are a few layers to this architecture and so I&amp;rsquo;m hoping this makes it harder for a compromise to be effective.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If someone compromises my laptop (i.e. gets access to it), then they can&amp;rsquo;t access the password data store as they can&amp;rsquo;t access my private key.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Although a compromise &lt;em&gt;could&lt;/em&gt; result in a key logger being installed and record what I type for my passphrase&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The only way to get my private key is to locate my remotely stored and safe USB that homes the raw private key contents.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If someone compromises the private git repository, they again can&amp;rsquo;t do anything with the contents without my private GPG key.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;when exporting a private key from GPG, it is by default encrypted with its passphrase (it&amp;rsquo;s not the raw key)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So what do you think? Is this good, bad or just plain terrible?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Please let me know your thoughts on twitter (&lt;a href=&#34;https://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;@integralist&lt;/a&gt;)&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/key-architecture/</guid>
      <link>https://www.integralist.co.uk/posts/key-architecture/</link>
      <pubDate>Sat, 10 Dec 2016 00:00:00 +0000</pubDate>
      <title>Key Architecture</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A few years ago when I was learning the &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go programming&#xA;language&lt;/a&gt; I created a gist and updated it on a regular&#xA;basis as a sort of cheat sheet. I stumbled across this gist recently and decided&#xA;I&amp;rsquo;d try and port it over to some form of semi-coherent blog post.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the code will not be updated in any way so&#xA;&lt;a href=&#34;http://dictionary.cambridge.org/dictionary/english/ymmv&#34; target=&#34;_blank&#34;&gt;YMMV&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What this isn&amp;rsquo;t, is a walk-through of how to write Go code. I&amp;rsquo;d suggest trying&#xA;the official &lt;a href=&#34;https://tour.golang.org/welcome/1&#34; target=&#34;_blank&#34;&gt;Go Tour&lt;/a&gt; which is really good&#xA;and covers a lot of ground. Instead I&amp;rsquo;m going to provide lots of example code in&#xA;the vein of a resource like &lt;a href=&#34;https://gobyexample.com/&#34; target=&#34;_blank&#34;&gt;Go by Example&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What this &lt;em&gt;is&lt;/em&gt;, is a barren wasteland of old code. Passers by are forewarned to&#xA;tread carefully.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there&amp;rsquo;s also not much in the way of code explanation, to the extent that&#xA;some of the testing examples are long and very context specific - you&amp;rsquo;ve been&#xA;warned&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Most of this Go code is old, so you may find some packages or information&#xA;possibly out of date (as in not the latest awesome thing) or maybe not that&#xA;great quality either.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Take this as what it is, a sharing exercise. Take what you need and leave the&#xA;rest. I wont be offended.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;private-repo-access&#34;&gt;Private Repo Access&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;go get&lt;/code&gt; uses HTTPS so to be able to pull dependencies from a private&#xA;repository, you&amp;rsquo;ll need to force it to use SSH so it can access your keys and&#xA;authorise the connection:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global url.&amp;quot;git@github.com:&amp;quot;.insteadOf &amp;quot;https://github.com/&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also restrict this to a single specific organisation if you prefer:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global url.&amp;quot;git@github.com:foo/&amp;quot;.insteadOf &amp;quot;https://github.com/foo/&amp;quot;`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So when you want a private dependency like: &lt;code&gt;git@github.com:foo/private.git&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go get github.com/foo/private&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;build-and-compilation&#34;&gt;Build and Compilation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of Go 1.5 you can use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;GOOS=darwin GOARCH=386 go build foo.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a quick reference of the values you can specify:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$GOOS     $GOARCH&#xA;darwin    386      -- 32 bit MacOSX&#xA;darwin    amd64    -- 64 bit MacOSX&#xA;freebsd   386&#xA;freebsd   amd64&#xA;linux     386      -- 32 bit Linux&#xA;linux     amd64    -- 64 bit Linux&#xA;linux     arm      -- RISC Linux&#xA;netbsd    386&#xA;netbsd    amd64&#xA;openbsd   386&#xA;openbsd   amd64&#xA;plan9     386&#xA;windows   386      -- 32 bit Windows&#xA;windows   amd64    -- 64 bit Windows&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can get a full list with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go tool dist list&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;gox&#34;&gt;Gox&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Gox is an alternative build tool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One time only commands for purpose of download/setup:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;go get github.com/mitchellh/gox&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;gox -build-toolchain&lt;/code&gt; (only necessary for Go &lt;code&gt;1.4.x&lt;/code&gt; and lower)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Compilation example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gox -osarch=&amp;quot;linux/amd64&amp;quot; -osarch=&amp;quot;darwin/amd64&amp;quot; -osarch=&amp;quot;windows/amd64&amp;quot; -output=&amp;quot;foobar.{{.OS}}&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will generate three files:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;foobar.darwin&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;foobar.linux&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;foobar.windows.exe&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;other-information&#34;&gt;Other information&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Use the &lt;code&gt;-a&lt;/code&gt; flag when running &lt;code&gt;go build&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In short, if you dont&amp;rsquo; use &lt;code&gt;go build -a -v .&lt;/code&gt; then Go won&amp;rsquo;t know if any packages&#xA;are missing (you can find the gory details&#xA;&lt;a href=&#34;https://medium.com/@felixge/why-you-should-use-go-build-a-or-gb-c469157d5c1b#.jf5orcwrj&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;build-time-dynamic-variables&#34;&gt;Build Time Dynamic Variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a global variable called &lt;code&gt;version&lt;/code&gt; in your &lt;code&gt;main&lt;/code&gt; package and&#xA;you want to update that value at build time:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go build -ldflags &amp;quot;-X main.version=foobar&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;A more realistic example would be to use some form of revision number of commit hash:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go build -ldflags &amp;quot;-X main.version=$(git rev-parse HEAD)&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another approach would be to have separate files for different &amp;lsquo;environments&amp;rsquo;&#xA;(all under the &lt;code&gt;main&lt;/code&gt; package). You would then use a code comment to indicate&#xA;what the environment was, and at build time you would tell the compiler which&#xA;version of the file to compile.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// +build prod&#xA;&#xA;package main&#xA;&#xA;func init() {&#xA;    version = 123&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You would compile the above &lt;code&gt;version&lt;/code&gt; variable using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go build -tags prod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;package-naming&#34;&gt;Package Naming&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In Go, the name of the package is used to refer to the exported item:&#xA;&lt;code&gt;fmt.Println&lt;/code&gt;, &lt;code&gt;http.RegisterFunc&lt;/code&gt; etc. Because the package name is so visible,&#xA;the package name should describe what the exported items are. Meaning, we&#xA;shouldn&amp;rsquo;t have packages named &lt;code&gt;util&lt;/code&gt; (as a common example of bad package naming)&#xA;because &lt;code&gt;util.JSONMarshal&lt;/code&gt; isn&amp;rsquo;t as efficient and effective as &lt;code&gt;json.Marshal&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another example of this that I found in my own code was &lt;code&gt;utils.CreateUser&lt;/code&gt;.&#xA;Later on during the project I had added &lt;code&gt;utils.CreateLegacyUser&lt;/code&gt;. When I&#xA;discovered what I had done I went back and made two separate packages &lt;code&gt;legacy&lt;/code&gt;&#xA;and &lt;code&gt;aws&lt;/code&gt; so that I could have a consistent &lt;code&gt;CreateUser&lt;/code&gt; function within both&#xA;(e.g. &lt;code&gt;aws.CreateUser&lt;/code&gt; and &lt;code&gt;legacy.CreateUser&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;dependency-information&#34;&gt;Dependency Information&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To see a list of dependencies for a given Go package you can utilise the &lt;code&gt;go list&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go list -json strconv &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which returns:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  &amp;quot;Dir&amp;quot;: &amp;quot;/usr/local/Cellar/go/1.5.2/libexec/src/strconv&amp;quot;,&#xA;  &amp;quot;ImportPath&amp;quot;: &amp;quot;strconv&amp;quot;,&#xA;  &amp;quot;Name&amp;quot;: &amp;quot;strconv&amp;quot;,&#xA;  &amp;quot;Doc&amp;quot;: &amp;quot;Package strconv implements conversions to and from string representations of basic data types.&amp;quot;,&#xA;  &amp;quot;Target&amp;quot;: &amp;quot;/usr/local/Cellar/go/1.5.2/libexec/pkg/darwin_amd64/strconv.a&amp;quot;,&#xA;  &amp;quot;Goroot&amp;quot;: true,&#xA;  &amp;quot;Standard&amp;quot;: true,&#xA;  &amp;quot;Root&amp;quot;: &amp;quot;/usr/local/Cellar/go/1.5.2/libexec&amp;quot;,&#xA;  &amp;quot;GoFiles&amp;quot;: [&#xA;    &amp;quot;atob.go&amp;quot;,&#xA;    &amp;quot;atof.go&amp;quot;,&#xA;    &amp;quot;atoi.go&amp;quot;,&#xA;    &amp;quot;decimal.go&amp;quot;,&#xA;    &amp;quot;doc.go&amp;quot;,&#xA;    &amp;quot;extfloat.go&amp;quot;,&#xA;    &amp;quot;ftoa.go&amp;quot;,&#xA;    &amp;quot;isprint.go&amp;quot;,&#xA;    &amp;quot;itoa.go&amp;quot;,&#xA;    &amp;quot;quote.go&amp;quot;&#xA;  ],&#xA;  &amp;quot;IgnoredGoFiles&amp;quot;: [&#xA;    &amp;quot;makeisprint.go&amp;quot;&#xA;  ],&#xA;  &amp;quot;Imports&amp;quot;: [&#xA;    &amp;quot;errors&amp;quot;,&#xA;    &amp;quot;math&amp;quot;,&#xA;    &amp;quot;unicode/utf8&amp;quot;&#xA;  ],&#xA;  &amp;quot;Deps&amp;quot;: [&#xA;    &amp;quot;errors&amp;quot;,&#xA;    &amp;quot;math&amp;quot;,&#xA;    &amp;quot;runtime&amp;quot;,&#xA;    &amp;quot;unicode/utf8&amp;quot;,&#xA;    &amp;quot;unsafe&amp;quot;&#xA;  ],&#xA;  &amp;quot;TestGoFiles&amp;quot;: [&#xA;    &amp;quot;internal_test.go&amp;quot;&#xA;  ],&#xA;  &amp;quot;XTestGoFiles&amp;quot;: [&#xA;    &amp;quot;atob_test.go&amp;quot;,&#xA;    &amp;quot;atof_test.go&amp;quot;,&#xA;    &amp;quot;atoi_test.go&amp;quot;,&#xA;    &amp;quot;decimal_test.go&amp;quot;,&#xA;    &amp;quot;example_test.go&amp;quot;,&#xA;    &amp;quot;fp_test.go&amp;quot;,&#xA;    &amp;quot;ftoa_test.go&amp;quot;,&#xA;    &amp;quot;itoa_test.go&amp;quot;,&#xA;    &amp;quot;quote_test.go&amp;quot;,&#xA;    &amp;quot;strconv_test.go&amp;quot;&#xA;  ],&#xA;  &amp;quot;XTestImports&amp;quot;: [&#xA;    &amp;quot;bufio&amp;quot;,&#xA;    &amp;quot;bytes&amp;quot;,&#xA;    &amp;quot;errors&amp;quot;,&#xA;    &amp;quot;fmt&amp;quot;,&#xA;    &amp;quot;log&amp;quot;,&#xA;    &amp;quot;math&amp;quot;,&#xA;    &amp;quot;math/rand&amp;quot;,&#xA;    &amp;quot;os&amp;quot;,&#xA;    &amp;quot;reflect&amp;quot;,&#xA;    &amp;quot;runtime&amp;quot;,&#xA;    &amp;quot;strconv&amp;quot;,&#xA;    &amp;quot;strings&amp;quot;,&#xA;    &amp;quot;testing&amp;quot;,&#xA;    &amp;quot;time&amp;quot;,&#xA;    &amp;quot;unicode&amp;quot;&#xA;  ]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t specify the &lt;code&gt;-json&lt;/code&gt; flag then the default behaviour is to filter&#xA;out the &lt;code&gt;ImportPath&lt;/code&gt; field from the above JSON output. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go list strconv&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Will return just the import path &lt;code&gt;strconv&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;go help list | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You can also utilise Go&amp;rsquo;s templating functionality on the returned JSON object&#xA;by adding the &lt;code&gt;-f&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go list -f &#39;{{join .Deps &amp;quot; &amp;quot;}}&#39; strconv&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which filters out the &lt;code&gt;Deps&lt;/code&gt; field, joins up all items it contains using&#xA;whitespace and subsequently returns:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;errors math runtime unicode/utf8 unsafe&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can do more complex things such as:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go list -f &#39;{{.ImportPath}} -&amp;gt; {{join .Imports &amp;quot; &amp;quot;}}&#39; compress/...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which will return something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;compress/bzip2 -&amp;gt; bufio io sort&#xA;compress/flate -&amp;gt; bufio fmt io math sort strconv&#xA;compress/gzip -&amp;gt; bufio compress/flate errors fmt hash hash/crc32 io time&#xA;compress/lzw -&amp;gt; bufio errors fmt io&#xA;compress/zlib -&amp;gt; bufio compress/flate errors fmt hash hash/adler32 io&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;dependency-management&#34;&gt;Dependency Management&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Update (August 2017): there is an official tool now called&#xA;&lt;a href=&#34;https://github.com/golang/dep&#34; target=&#34;_blank&#34;&gt;dep&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;There are many dependency management tools, these are the few that I&amp;rsquo;ve tried&#xA;(in this order): godeps, gb, glide. Let&amp;rsquo;s review each of them to see how they&#xA;work:&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;godeps&#34;&gt;Godeps&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When running &lt;code&gt;go get &amp;lt;dependency&amp;gt;&lt;/code&gt; locally, Go will stick the dependency in the&#xA;folder defined by your &lt;code&gt;$GOPATH&lt;/code&gt; variable. So when you build your code into a&#xA;binary using &lt;code&gt;go build &amp;lt;script&amp;gt;&lt;/code&gt; it&amp;rsquo;ll bake the dependencies into the binary&#xA;(i.e. the binary is statically linked).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if someone pulls down your repo and tries to do a build from your code, then&#xA;they&amp;rsquo;ll need to have a network connection to pull down the dependencies as their&#xA;&lt;code&gt;$GOPATH&lt;/code&gt; might not have those dependencies yet (unless the user manually&#xA;executes &lt;code&gt;go get&lt;/code&gt; for each dependency required). Also the dependencies they&#xA;subsequently pull down could be a more recent (and untested version) of each&#xA;dependency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to make this situation better we can use&#xA;&lt;a href=&#34;https://github.com/tools/godep&#34; target=&#34;_blank&#34;&gt;Godep&lt;/a&gt; to stick all your dependencies within a&#xA;&lt;code&gt;Godeps&lt;/code&gt; folder inside your project directory. You can then use &lt;code&gt;godep save -r ./...&lt;/code&gt; to automatically update all your references to point to that local&#xA;folder.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you might need to remove the &lt;code&gt;Godeps&lt;/code&gt; folder and run &lt;code&gt;go get&lt;/code&gt; if you get&#xA;strange conflicts. The &lt;code&gt;./...&lt;/code&gt; means to target all &lt;code&gt;.go&lt;/code&gt; files&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This way users who clone your repo don&amp;rsquo;t need an internet connection to pull the&#xA;dependencies, as they already have them. But also they&amp;rsquo;ll have the correct&#xA;versions of the dependencies. This acts like a &lt;code&gt;Gemfile.lock&lt;/code&gt; as you would&#xA;typically find in the Ruby world.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;gb&#34;&gt;Gb&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go get -u github.com/constabulary/gb/...&#xA;gb vendor fetch &amp;lt;pkg&amp;gt;&#xA;gb build all&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll need the following structure:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;├── src&#xA;│   ├── foo&#xA;│   │   └── main.go&#xA;└── vendor&#xA;    ├── manifest&#xA;    └── src&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;vendor&lt;/code&gt; directory is auto-generated by the &lt;code&gt;gb vendor fetch &amp;lt;pkg&amp;gt;&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;glide&#34;&gt;Glide&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is now my preferred dependency management tool, as it works just like&#xA;existing tools in other languages (e.g. Ruby&amp;rsquo;s Bundler or Node&amp;rsquo;s NPM) and so&#xA;consistency is a plus.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It also provides the ability (like gb) to not commit dependencies but have&#xA;specific versions vendored when running a simple command.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go get github.com/Masterminds/glide&#xA;export GO15VENDOREXPERIMENT=1       # or use 1.6&#xA;glide init                          # generates glide.yaml&#xA;glide install                       # installs from lock file (creates it if not found)&#xA;glide update                        # updates dependencies and updates lock file&#xA;glide list                          # shows vendored deps&#xA;go test $(glide novendor)           # test only your package (not vendored packages)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to add a new dependency &lt;code&gt;glide get &amp;lt;pkg_name&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;documentation&#34;&gt;Documentation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Godoc&lt;/code&gt; is the original implementation for viewing documentation. Previous to&#xA;&lt;code&gt;Godoc&lt;/code&gt; there was &lt;code&gt;go doc&lt;/code&gt;, but that was removed and then added &lt;em&gt;back&lt;/em&gt; with&#xA;totally different functionality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The syntax structure for &lt;code&gt;go doc&lt;/code&gt; is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go doc &amp;lt;pkg&amp;gt;&#xA;go doc &amp;lt;sym&amp;gt;[.&amp;lt;method&amp;gt;]&#xA;go doc [&amp;lt;pkg&amp;gt;].&amp;lt;sym&amp;gt;[.&amp;lt;method&amp;gt;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here are some examples of using &lt;code&gt;go doc&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go doc json # same as go doc encoding/json&#xA;go doc json.Number&#xA;go doc json.Number.Float64&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is the same thing but using &lt;code&gt;godoc&lt;/code&gt; (where the syntax structure is &lt;code&gt;godoc &amp;lt;pkg&amp;gt; &amp;lt;symbol&amp;gt;&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;godoc encoding/json # unlike &amp;quot;go doc json&amp;quot;, &amp;quot;godoc json&amp;quot; doesn&#39;t work as it&#39;s not a fully qualified path&#xA;godoc encoding/json Number&#xA;godoc -src builtin make | less&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Unlike with &lt;code&gt;go doc&lt;/code&gt;, &lt;code&gt;godoc&lt;/code&gt; doesn&amp;rsquo;t allow filtering by &lt;code&gt;&amp;lt;method&amp;gt;&lt;/code&gt;&lt;br&gt;&#xA;It only goes as far as &lt;code&gt;&amp;lt;pkg&amp;gt; &amp;lt;symbol&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can use &lt;code&gt;&amp;lt;pkg&amp;gt; &amp;lt;symbol&amp;gt; &amp;lt;method&amp;gt;&lt;/code&gt;&lt;br&gt;&#xA;and the method will be included in the results&lt;br&gt;&#xA;but you&amp;rsquo;ll need to search for the method manually&lt;br&gt;&#xA;&lt;code&gt;godoc -src net/http Request ParseForm | less&lt;/code&gt;&lt;br&gt;&#xA;here is a similar result using &lt;code&gt;go doc&lt;/code&gt;&lt;br&gt;&#xA;&lt;code&gt;go doc http.Request.ParseForm | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The purpose of &lt;code&gt;go doc&lt;/code&gt; was to provide a simplistic cli documentation viewer,&#xA;whereas &lt;code&gt;Godoc&lt;/code&gt; has many more features available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;go doc&lt;/code&gt; command also works not only with Go&amp;rsquo;s own library&amp;rsquo;s but your own&#xA;custom packages as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are some differences in what is returned though between &lt;code&gt;godoc&lt;/code&gt; and &lt;code&gt;go doc&lt;/code&gt; (mainly the latter is more succinct/compact so you can find the&#xA;functions/types you&amp;rsquo;re after and then you can expand into those once you&amp;rsquo;ve&#xA;found them; &lt;code&gt;godoc&lt;/code&gt; is harder to sift through on the command line)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;godoc-encoding-json-encoder&#34;&gt;&lt;code&gt;godoc encoding/json Encoder&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type Encoder struct {&#xA;    // contains filtered or unexported fields&#xA;}&#xA;    An Encoder writes JSON objects to an output stream.&#xA;&#xA;func NewEncoder(w io.Writer) *Encoder&#xA;    NewEncoder returns a new encoder that writes to w.&#xA;&#xA;func (enc *Encoder) Encode(v interface{}) error&#xA;    Encode writes the JSON encoding of v to the stream, followed by a&#xA;    newline character.&#xA;&#xA;    See the documentation for Marshal for details about the conversion of Go&#xA;    values to JSON.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;go-doc-encoding-json-encoder&#34;&gt;&lt;code&gt;go doc encoding/json Encoder&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type Encoder struct {&#xA;        // Has unexported fields.&#xA;}&#xA;&#xA;    An Encoder writes JSON objects to an output stream.&#xA;&#xA;func NewEncoder(w io.Writer) *Encoder&#xA;func (enc *Encoder) Encode(v interface{}) error&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice the functions don&amp;rsquo;t have their documentation notes printed with &lt;code&gt;go doc&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;One other thing &lt;code&gt;godoc&lt;/code&gt; has over &lt;code&gt;go doc&lt;/code&gt; is the ability to view the source code&#xA;using the &lt;code&gt;-src&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;godoc -src builtin make | less&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;godoc&lt;/code&gt; tool also has a full browser documentation suite available and&#xA;allows you to generate HTML documentation for your project&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;full-browser-documentation&#34;&gt;Full Browser Documentation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Start a local documentation server and allow indexing (which takes a few&#xA;minutes; you have to just keep trying the search until it&amp;rsquo;s done)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;godoc -http &#39;:6060&#39; -index&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then open a new terminal pane and search via cli if you prefer (rather&#xA;than open up a browser to &lt;a href=&#34;http://localhost:6060/)&#34; target=&#34;_blank&#34;&gt;http://localhost:6060/)&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;godoc -q tls | less&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also have the playground available if you need it in the browser, but it&#xA;does require an internet connection to compile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;godoc -http &#39;:6060&#39; -play&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see also &lt;a href=&#34;https://gist.github.com/Integralist/cf76668bc46d75058ab5f566d96ce74a&#34; target=&#34;_blank&#34;&gt;examples&#xA;here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Test files are placed in the same directory as the file/package being tested.&#xA;The convention is to use the same file name but suffix it with &lt;code&gt;_test&lt;/code&gt;. So&#xA;&lt;code&gt;foo.go&lt;/code&gt; would have another file next to it called &lt;code&gt;foo_test.go&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Run the tests: &lt;code&gt;go test -v ./...&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also run a specific test like so: &lt;code&gt;go test -v command/foo_test.go&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;remember that your test file should have the same package name as your&#xA;code being tested. This means the test file will have access to all the public&#xA;functions and variables of that package (and so subsequently it&amp;rsquo;ll have access&#xA;to the code being tested)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is a simple test example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package foo&#xA;&#xA;import &amp;quot;testing&amp;quot;&#xA;&#xA;func TestBasics(t *testing.T) {&#xA;  expect := &amp;quot;abc&amp;quot;&#xA;  actual := &amp;quot;def&amp;quot;&#xA;&#xA;  if actual != expect {&#xA;    t.Errorf(&amp;quot;expected %s, actual %s&amp;quot;, expect, actual)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output from running this test will be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;=== RUN   TestBasics&#xA;--- FAIL: TestBasics (0.00s)&#xA;        foo_test.go:10: expected abc, actual def&#xA;FAIL&#xA;exit status 1&#xA;FAIL    command-line-arguments  0.004s&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following example program demonstrates how to mock an io function so that&#xA;we&amp;rsquo;re not reliant on reading from disk in our test suite.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;io/ioutil&amp;quot;&#xA;)&#xA;&#xA;type fooIO func(string) ([]byte, error)&#xA;&#xA;func getContents(fio fooIO, path string) (string, error) {&#xA;  f, err := fio(path)&#xA;  if err != nil {&#xA;    return &amp;quot;&amp;quot;, err&#xA;  }&#xA;  return string(f), nil&#xA;}&#xA;&#xA;func main() {&#xA;  contents, err := getContents(ioutil.ReadFile, &amp;quot;example.txt&amp;quot;)&#xA;  if err != nil {&#xA;    fmt.Println(err)&#xA;  }&#xA;  fmt.Println(contents)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the test:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;testing&amp;quot;&#xA;&#xA;var expectation = &amp;quot;pretend to read from disk&amp;quot;&#xA;&#xA;func fakeReadFileSuccess(path string) ([]byte, error) {&#xA;  return []byte(expectation), nil&#xA;}&#xA;&#xA;func TestIO(t *testing.T) {&#xA;  contents, _ := getContents(fakeReadFileSuccess, &amp;quot;dont-exist.txt&amp;quot;)&#xA;&#xA;  if contents != expectation {&#xA;    t.Errorf(&amp;quot;Expected &#39;%s&#39; but got &#39;%s&#39;&amp;quot;, expectation, contents)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You could also probably use an interface there, but we&amp;rsquo;ve gone with a &lt;code&gt;func&lt;/code&gt;&#xA;type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s another program that does something similar where we mock a function that&#xA;expects a particular interface:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type FooIO interface {&#xA;  Read() string&#xA;}&#xA;&#xA;type Foo struct{}&#xA;&#xA;func (f *Foo) Read() string {&#xA;  return &amp;quot;We READ something from disk&amp;quot;&#xA;}&#xA;&#xA;func Stuff(f FooIO) string {&#xA;  return f.Read()&#xA;}&#xA;&#xA;func main() {&#xA;  foo := &amp;amp;Foo{}&#xA;  contents := Stuff(foo)&#xA;  fmt.Println(contents)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s our test:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;testing&amp;quot;&#xA;&#xA;  &amp;quot;github.com/stretchr/testify/assert&amp;quot;&#xA;)&#xA;&#xA;type FakeFoo struct{}&#xA;&#xA;func (s *FakeFoo) Read() string {&#xA;  return &amp;quot;We &#39;pretend&#39; to READ something from disk&amp;quot;&#xA;}&#xA;&#xA;func TestSomething(t *testing.T) {&#xA;  assert := assert.New(t)&#xA;&#xA;  foo := &amp;amp;FakeFoo{}&#xA;  contents := Stuff(foo)&#xA;&#xA;  assert.Equal(contents, &amp;quot;We &#39;pretend&#39; to READ something from disk&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;more-test-examples&#34;&gt;More Test Examples&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Faking HTTP and WebServers can be a bit tricky:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package requester&#xA;&#xA;import (&#xA;  &amp;quot;bytes&amp;quot;&#xA;  &amp;quot;encoding/json&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;io/ioutil&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;net/http/httptest&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;  &amp;quot;strconv&amp;quot;&#xA;  &amp;quot;testing&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;&#xA;  &amp;quot;github.com/bbc/mozart-requester/src/aggregator&amp;quot;&#xA;  &amp;quot;github.com/julienschmidt/httprouter&amp;quot;&#xA;)&#xA;&#xA;func TestSuccessResponse(t *testing.T) {&#xA;  upstream := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/json&amp;quot;)&#xA;      fmt.Fprintln(w, `{&amp;quot;head&amp;quot;:[ &amp;quot;foo&amp;quot; ],&amp;quot;bodyInline&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;bodyLast&amp;quot;:[ &amp;quot;baz&amp;quot; ]}`)&#xA;    }&#xA;  ))&#xA;  defer upstream.Close()&#xA;&#xA;  router := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      Process(w, r, httprouter.Params{})&#xA;    }&#xA;  ))&#xA;  defer router.Close()&#xA;&#xA;  var config = []byte(fmt.Sprintf(`{&#xA;    &amp;quot;components&amp;quot;:[&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;foo&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true},&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true}&#xA;    ]&#xA;  }`, upstream.URL, upstream.URL))&#xA;&#xA;  req, err := http.NewRequest(&amp;quot;POST&amp;quot;, router.URL, bytes.NewBuffer(config))&#xA;&#xA;  client := &amp;amp;http.Client{}&#xA;  resp, err := client.Do(req)&#xA;  if err != nil {&#xA;    panic(err)&#xA;  }&#xA;&#xA;  defer resp.Body.Close()&#xA;  body, _ := ioutil.ReadAll(resp.Body)&#xA;&#xA;  var result aggregator.Result&#xA;  json.Unmarshal(body, &amp;amp;result)&#xA;&#xA;  expectedStatus := &amp;quot;success&amp;quot;&#xA;  if result.Summary != expectedStatus {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;,&#xA;    result.Summary, expectedStatus)&#xA;  }&#xA;&#xA;  expectedLength := 2&#xA;  if len(result.Components) != expectedLength {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%d&#39;\ndidn&#39;t match the expectation:\n &#39;%d&#39;&amp;quot;, &#xA;    len(result.Components), expectedLength)&#xA;  }&#xA;}&#xA;&#xA;func TestFailureResponse(t *testing.T) {&#xA;  healthyUpstream := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/json&amp;quot;)&#xA;      fmt.Fprintln(w, `{&amp;quot;head&amp;quot;:[ &amp;quot;foo&amp;quot; ],&amp;quot;bodyInline&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;bodyLast&amp;quot;:[ &amp;quot;baz&amp;quot; ]}`)&#xA;    }&#xA;  ))&#xA;  defer healthyUpstream.Close()&#xA;&#xA;  failingUpstream := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;text/plain; charset=utf-8&amp;quot;)&#xA;      w.WriteHeader(http.StatusNotFound)&#xA;      fmt.Fprintln(w, &amp;quot;404 page not found&amp;quot;)&#xA;    }&#xA;  ))&#xA;  defer failingUpstream.Close()&#xA;&#xA;  router := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      Process(w, r, httprouter.Params{})&#xA;    }&#xA;  ))&#xA;  defer router.Close()&#xA;&#xA;  var config = []byte(fmt.Sprintf(`{&#xA;    &amp;quot;components&amp;quot;:[&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;foo&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true},&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true}&#xA;    ]&#xA;  }`, healthyUpstream.URL, failingUpstream.URL))&#xA;&#xA;  req, err := http.NewRequest(&amp;quot;POST&amp;quot;, router.URL, bytes.NewBuffer(config))&#xA;&#xA;  client := &amp;amp;http.Client{}&#xA;  resp, err := client.Do(req)&#xA;  if err != nil {&#xA;    panic(err)&#xA;  }&#xA;&#xA;  defer resp.Body.Close()&#xA;  body, _ := ioutil.ReadAll(resp.Body)&#xA;&#xA;  var result aggregator.Result&#xA;  json.Unmarshal(body, &amp;amp;result)&#xA;&#xA;  expectedSummary := &amp;quot;failure&amp;quot;&#xA;  if result.Summary != expectedSummary {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;, &#xA;    result.Summary, expectedSummary)&#xA;  }&#xA;&#xA;  expectedLength := 2&#xA;  if len(result.Components) != expectedLength {&#xA;    t.Errorf(&amp;quot;The response length:\n &#39;%d&#39;\ndidn&#39;t match the expectation:\n &#39;%d&#39;&amp;quot;, &#xA;    len(result.Components), expectedLength)&#xA;  }&#xA;&#xA;  expectedStatus := []int{}&#xA;  for _, value := range result.Components {&#xA;    if value.Status == 404 {&#xA;      expectedStatus = append(expectedStatus, value.Status)&#xA;    }&#xA;  }&#xA;  if len(expectedStatus) &amp;lt; 1 || len(expectedStatus) &amp;gt; 1 {&#xA;    t.Errorf(&amp;quot;The response length:\n &#39;%d&#39;\ndidn&#39;t match the expectation:\n &#39;%d&#39;&amp;quot;, &#xA;    len(expectedStatus), 1)&#xA;  }&#xA;}&#xA;&#xA;func TestSlowResponse(t *testing.T) {&#xA;  healthyUpstream := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/json&amp;quot;)&#xA;      fmt.Fprintln(w, `{&amp;quot;head&amp;quot;:[ &amp;quot;foo&amp;quot; ],&amp;quot;bodyInline&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;bodyLast&amp;quot;:[ &amp;quot;baz&amp;quot; ]}`)&#xA;    }&#xA;  ))&#xA;  defer healthyUpstream.Close()&#xA;&#xA;  slowUpstream := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      timeout, err := strconv.Atoi(os.Getenv(&amp;quot;COMPONENT_TIMEOUT&amp;quot;))&#xA;      if err != nil {&#xA;        t.Errorf(&amp;quot;COMPONENT_TIMEOUT: %s&amp;quot;, err.Error())&#xA;      }&#xA;      time.Sleep(time.Duration(timeout) * time.Millisecond)&#xA;      w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/json&amp;quot;)&#xA;      fmt.Fprintln(w, `{&amp;quot;head&amp;quot;:[ &amp;quot;foo&amp;quot; ],&amp;quot;bodyInline&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;bodyLast&amp;quot;:[ &amp;quot;baz&amp;quot; ]}`)&#xA;    }&#xA;  ))&#xA;  defer slowUpstream.Close()&#xA;&#xA;  router := httptest.NewServer(http.HandlerFunc(&#xA;    func(w http.ResponseWriter, r *http.Request) {&#xA;      Process(w, r, httprouter.Params{})&#xA;    }&#xA;  ))&#xA;  defer router.Close()&#xA;&#xA;  var config = []byte(fmt.Sprintf(`{&#xA;    &amp;quot;components&amp;quot;:[&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;foo&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true},&#xA;      {&amp;quot;id&amp;quot;:&amp;quot;bar&amp;quot;,&amp;quot;endpoint&amp;quot;:&amp;quot;%s&amp;quot;,&amp;quot;must_succeed&amp;quot;:true}&#xA;    ]&#xA;  }`, healthyUpstream.URL, slowUpstream.URL))&#xA;&#xA;  req, err := http.NewRequest(&amp;quot;POST&amp;quot;, router.URL, bytes.NewBuffer(config))&#xA;&#xA;  client := &amp;amp;http.Client{}&#xA;  resp, err := client.Do(req)&#xA;  if err != nil {&#xA;    panic(err)&#xA;  }&#xA;&#xA;  defer resp.Body.Close()&#xA;  body, _ := ioutil.ReadAll(resp.Body)&#xA;&#xA;  var result aggregator.Result&#xA;  json.Unmarshal(body, &amp;amp;result)&#xA;&#xA;  expectedStatus := 408&#xA;  for _, value := range result.Components {&#xA;    if value.ID == &amp;quot;bar&amp;quot; &amp;amp;&amp;amp; value.Status != expectedStatus {&#xA;      t.Errorf(&amp;quot;The response:\n &#39;%d&#39;\ndidn&#39;t match the expectation:\n &#39;%d&#39;&amp;quot;, &#xA;      value.Status, expectedStatus)&#xA;    }&#xA;  }&#xA;&#xA;  expectedSummary := &amp;quot;failure&amp;quot;&#xA;  if result.Summary != expectedSummary {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;, &#xA;    result.Summary, expectedSummary)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I typically run my tests using Make, but it ultimately looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pushd src &amp;amp;&amp;amp; APP_ENV=test COMPONENT_TIMEOUT=100 go test -v $(glide novendor) &amp;amp;&amp;amp; popd&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s another example of a test needing to fake things:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package retriever&#xA;&#xA;import (&#xA;  &amp;quot;bytes&amp;quot;&#xA;  &amp;quot;io/ioutil&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;strings&amp;quot;&#xA;  &amp;quot;testing&amp;quot;&#xA;&#xA;  &amp;quot;github.com/PuerkitoBio/goquery&amp;quot;&#xA;)&#xA;&#xA;const href = &amp;quot;http://bar.com/&amp;quot;&#xA;const url = &amp;quot;http://foo.com/&amp;quot;&#xA;&#xA;var body string&#xA;&#xA;func fakeNewDocument(url string) (*goquery.Document, error) {&#xA;  body = strings.Replace(body, &amp;quot;{}&amp;quot;, href, 1)&#xA;&#xA;  resp := &amp;amp;http.Response{&#xA;    Status:        &amp;quot;200 OK&amp;quot;,&#xA;    StatusCode:    200,&#xA;    Proto:         &amp;quot;HTTP/1.0&amp;quot;,&#xA;    ProtoMajor:    1,&#xA;    ProtoMinor:    0,&#xA;    Body:          ioutil.NopCloser(bytes.NewBufferString(body)),&#xA;    ContentLength: int64(len(body)),&#xA;    Request:       &amp;amp;http.Request{},&#xA;  }&#xA;&#xA;  return goquery.NewDocumentFromResponse(resp)&#xA;}&#xA;&#xA;func TestRetrieveReturnValue(t *testing.T) {&#xA;  // {} interpolated with constant&#39;s value&#xA;  body = `&#xA;    &amp;lt;html&amp;gt;&#xA;      &amp;lt;body&amp;gt;&#xA;        &amp;lt;div class=&amp;quot;productInfo&amp;quot;&amp;gt;&#xA;          &amp;lt;a href=&amp;quot;{}&amp;quot;&amp;gt;Bar&amp;lt;/a&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;      &amp;lt;/body&amp;gt;&#xA;    &amp;lt;html&amp;gt;&#xA;  `&#xA;  coll, _ := Retrieve(url, fakeNewDocument)&#xA;&#xA;  if response := coll[0]; response != href {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;, &#xA;    response, href)&#xA;  }&#xA;}&#xA;&#xA;func TestRetrieveMissingAttributeReturnsEmptySlice(t *testing.T) {&#xA;  // href attribute is missing from anchor element&#xA;  body = `&#xA;    &amp;lt;html&amp;gt;&#xA;      &amp;lt;body&amp;gt;&#xA;        &amp;lt;div class=&amp;quot;productInfo&amp;quot;&amp;gt;&#xA;          &amp;lt;a&amp;gt;Bar&amp;lt;/a&amp;gt;&#xA;        &amp;lt;/div&amp;gt;&#xA;      &amp;lt;/body&amp;gt;&#xA;    &amp;lt;html&amp;gt;&#xA;  `&#xA;  coll, _ := Retrieve(url, fakeNewDocument)&#xA;&#xA;  if response := coll; len(response) &amp;gt; 0 {&#xA;    t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;, &#xA;    response, &amp;quot;[http://bar.com/]&amp;quot;)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package scraper&#xA;&#xA;import &amp;quot;testing&amp;quot;&#xA;&#xA;func TestScrapeResults(t *testing.T) {&#xA;  getItem = func(url string) {&#xA;    defer wg.Done()&#xA;&#xA;    ch &amp;lt;- Item{&#xA;      &amp;quot;FooTitle&amp;quot;,&#xA;      &amp;quot;FooSize&amp;quot;,&#xA;      &amp;quot;10.00&amp;quot;,&#xA;      &amp;quot;FooDescription&amp;quot;,&#xA;    }&#xA;  }&#xA;&#xA;  urls := []string{&#xA;    &amp;quot;http://foo.com/&amp;quot;,&#xA;    &amp;quot;http://bar.com/&amp;quot;,&#xA;    &amp;quot;http://baz.com/&amp;quot;,&#xA;  }&#xA;&#xA;  result := Scrape(urls)&#xA;  first := result.Items[0]&#xA;&#xA;  var suite = []struct {&#xA;    response string&#xA;    expected string&#xA;  }{&#xA;    {first.Title, &amp;quot;FooTitle&amp;quot;},&#xA;    {first.Size, &amp;quot;FooSize&amp;quot;},&#xA;    {first.UnitPrice, &amp;quot;10.00&amp;quot;},&#xA;    {first.Description, &amp;quot;FooDescription&amp;quot;},&#xA;    {result.Total, &amp;quot;30.00&amp;quot;},&#xA;  }&#xA;&#xA;  for _, v := range suite {&#xA;    if v.response != v.expected {&#xA;      err(v.response, v.expected, t)&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;func err(response, expected string, t *testing.T) {&#xA;  t.Errorf(&amp;quot;The response:\n &#39;%s&#39;\ndidn&#39;t match the expectation:\n &#39;%s&#39;&amp;quot;, &#xA;  response, expected)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;logging&#34;&gt;Logging&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Using the standard Logger:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;info := log.New(os.Stdout, &amp;quot;STUFF: &amp;quot;, log.Ldate|log.Ltime|log.Lshortfile)&#xA;info.Println(&amp;quot;Starting up!!!&amp;quot;)&#xA;&#xA;f, e := os.Create(&amp;quot;test.log&amp;quot;)&#xA;if e != nil {&#xA;  log.Fatal(&amp;quot;Failed to create log file&amp;quot;)&#xA;}&#xA;&#xA;logfile := log.New(f, &amp;quot;STUFF: &amp;quot;, log.Ldate|log.Ltime|log.Lshortfile)&#xA;logfile.Println(&amp;quot;Starting up!!!&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Using Logrus:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;os&amp;quot;&#xA;&#xA;  log &amp;quot;github.com/Sirupsen/logrus&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  // Standard stdout ASCII logging&#xA;  log.WithFields(log.Fields{&#xA;    &amp;quot;animal&amp;quot;: &amp;quot;walrus&amp;quot;,&#xA;  }).Info(&amp;quot;A walrus appears&amp;quot;)&#xA;&#xA;  // JSON style structured logging&#xA;  log.SetFormatter(&amp;amp;log.JSONFormatter{})&#xA;  f, e := os.Create(&amp;quot;logs&amp;quot;)&#xA;  if e != nil {&#xA;    log.Fatal(&amp;quot;Failed to create log file&amp;quot;)&#xA;  }&#xA;  log.SetOutput(f)&#xA;  log.WithFields(log.Fields{&#xA;    &amp;quot;animal&amp;quot;: &amp;quot;walrus&amp;quot;,&#xA;    &amp;quot;size&amp;quot;:   10,&#xA;  }).Info(&amp;quot;A group of walrus emerges from the ocean&amp;quot;)&#xA;  /*&#xA;      {&#xA;        &amp;quot;animal&amp;quot;: &amp;quot;walrus&amp;quot;,&#xA;        &amp;quot;level&amp;quot;: &amp;quot;info&amp;quot;,&#xA;        &amp;quot;msg&amp;quot;: &amp;quot;A group of walrus emerges from the ocean&amp;quot;,&#xA;        &amp;quot;size&amp;quot;: 10,&#xA;        &amp;quot;time&amp;quot;: &amp;quot;2015-12-22T13:58:46Z&amp;quot;&#xA;      }&#xA;  */&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;godo&#34;&gt;Godo&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Godo is a build tool in a similar vein to rake or gulp.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example is taken from my own project&#xA;&lt;a href=&#34;https://github.com/Integralist/Go-Requester&#34; target=&#34;_blank&#34;&gt;go-requester&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;&#xA;  do &amp;quot;gopkg.in/godo.v2&amp;quot;&#xA;)&#xA;&#xA;func tasks(p *do.Project) {&#xA;  if pwd, err := os.Getwd(); err == nil {&#xA;    do.Env = fmt.Sprintf(&amp;quot;GOPATH=%s/vendor::$GOPATH&amp;quot;, pwd)&#xA;  }&#xA;&#xA;  p.Task(&amp;quot;server&amp;quot;, nil, func(c *do.Context) {&#xA;    c.Start(&amp;quot;main.go ./config/page.yaml&amp;quot;, do.M{&amp;quot;$in&amp;quot;: &amp;quot;./&amp;quot;})&#xA;  }).Src(&amp;quot;**/*.go&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;  do.Godo(tasks)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;import-race-conditions&#34;&gt;Import Race Conditions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you import a package within a Go script, only the public functions and&#xA;variables are exposed for the caller to utilise. So if you need a package to&#xA;execute some bootstrapping code at the point of it being &lt;em&gt;loaded&lt;/em&gt;, then you&amp;rsquo;ll&#xA;need to stick it inside of an &lt;code&gt;init&lt;/code&gt; function.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can have multiple &lt;code&gt;init&lt;/code&gt; functions inside a package e.g. one per&#xA;file within the package namespace&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But be careful using &lt;code&gt;init&lt;/code&gt; as it can result in a race condition.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve hit an issue where I had something like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;main.go&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;foo.go&lt;/code&gt; (imported by &lt;code&gt;main.go&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;bar.go&lt;/code&gt; (imported by &lt;code&gt;foo.go&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Each one of these packages had its own &lt;code&gt;init&lt;/code&gt; function and ultimately the&#xA;&lt;code&gt;bar.go&lt;/code&gt;&amp;rsquo;s &lt;code&gt;init&lt;/code&gt; function was being run first, followed by the &lt;code&gt;foo.go&lt;/code&gt;&amp;rsquo;s&#xA;&lt;code&gt;init&lt;/code&gt; function and finally followed by the &lt;code&gt;main.go&lt;/code&gt;&amp;rsquo;s &lt;code&gt;init&lt;/code&gt; function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this was an issue was because &lt;code&gt;main.go&lt;/code&gt; was loading some environment&#xA;variables needed by &lt;code&gt;bar.go&lt;/code&gt; but those variables weren&amp;rsquo;t available by the time&#xA;the &lt;code&gt;bar.go&lt;/code&gt; was running as that happened &lt;em&gt;before&lt;/em&gt; &lt;code&gt;main.go&lt;/code&gt;&amp;rsquo;s &lt;code&gt;init&lt;/code&gt; function&#xA;had executed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution was to rename all the &lt;code&gt;init&lt;/code&gt; functions to &lt;code&gt;Init&lt;/code&gt; and explicitly&#xA;call them to bootstrap the package when needed (i.e. they didn&amp;rsquo;t automatically&#xA;bootstrap themselves and so we avoided that race condition).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;new-vs-make&#34;&gt;New vs Make&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;func new(Type) *Type&lt;/code&gt;: allocate memory for custom-user type&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;func make(Type, size IntegerType) Type&lt;/code&gt;: allocate memory for builtin types&#xA;(Slice, Map, Chan)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;  foo := make(map[string]string)&#xA;  fmt.Println(foo) // map[]&#xA;  foo[&amp;quot;k1&amp;quot;] = &amp;quot;bar&amp;quot;&#xA;  fmt.Println(foo) // map[k1:bar]&#xA;  fmt.Println(foo[&amp;quot;k1&amp;quot;]) // bar&#xA;  &#xA;  type bar [5]int&#xA;  b := new(bar)&#xA;  fmt.Println(b) // &amp;amp;[0 0 0 0 0]&#xA;  b[0] = 1&#xA;  fmt.Println(b) // &amp;amp;[1 0 0 0 0]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-types&#34;&gt;Custom Types&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;bytes&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;)&#xA;&#xA;type path []byte // our custom Type&#xA;&#xA;// method attached to our custom Type&#xA;func (p *path) TruncateAtFinalSlash() {&#xA;  i := bytes.LastIndex(*p, []byte(&amp;quot;/&amp;quot;))&#xA;&#xA;  if i &amp;gt;= 0 {&#xA;    *p = (*p)[0:i]&#xA;  }&#xA;}&#xA;&#xA;func main() {&#xA;  pathName := path(&amp;quot;/usr/bin/tso&amp;quot;) // Conversion from string to path.&#xA;&#xA;  pathName.TruncateAtFinalSlash()&#xA;&#xA;  fmt.Printf(&amp;quot;%s\n&amp;quot;, pathName)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternative example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type foo [5]int&#xA;&#xA;func main() {&#xA;  f := new(foo)&#xA;  fmt.Println(f) // &amp;amp;[0 0 0 0 0]&#xA;  f[0] = 1&#xA;  fmt.Println(f) // &amp;amp;[1 0 0 0 0]&#xA;  f.Bar()&#xA;  fmt.Println(f) // &amp;amp;[1 2 0 0 0]&#xA;&#xA;  // We can coerce custom types like we can with built-in types&#xA;  b := foo([5]int{9, 9, 9})&#xA;  fmt.Println(b) // [9 9 9 0 0]&#xA;  &#xA;  // Check the types&#xA;  fmt.Printf(&amp;quot;%T\n&amp;quot;, b)               // main.foo&#xA;  fmt.Printf(&amp;quot;%T\n&amp;quot;, [5]int{9, 9, 9}) // [5]int&#xA;}&#xA;&#xA;func (f *foo) Bar() {&#xA;  f[1] = 2&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-errors&#34;&gt;Custom Errors&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;errors&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;)&#xA;&#xA;type CustomErr interface {&#xA;    error&#xA;}&#xA;&#xA;var (&#xA;    CustomError = errors.New(&amp;quot;Some Custom Error&amp;quot;)&#xA;)&#xA;&#xA;// we return an &#39;error&#39; type specifically&#xA;// CustomError is indeed an error type, so returning that works&#xA;// but also, the interface CustomErr means the CustomError var &#xA;// _is_ a CustomErr type too&#xA;func succeed(b bool) (string, error) {&#xA;    if b {&#xA;        return &amp;quot;success&amp;quot;, nil&#xA;    }&#xA;    return &amp;quot;&amp;quot;, CustomError&#xA;}&#xA;&#xA;func main() {&#xA;    fmt.Println(CustomError) // Some Custom Error&#xA;&#xA;    resp, err := succeed(false)&#xA;    if err != nil {&#xA;        t, ok := err.(CustomErr)&#xA;        if ok {&#xA;            fmt.Printf(&amp;quot;t is a custom error &#39;%+v&#39; (%T)\n&amp;quot;, t, t)&#xA;        }&#xA;        fmt.Println(err) // Some Custom Error&#xA;    }&#xA;    fmt.Println(resp) // success (only if succeed(true) is called)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another form of custom error can be seen using a struct:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type errCustom struct {&#xA;    message string&#xA;    code    int&#xA;}&#xA;&#xA;func (e errCustom) Error() string {&#xA;    return fmt.Sprintf(&amp;quot;error message: %s (code: %d)&amp;quot;, e.message, e.code)&#xA;} &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We would then implement the struct with the specific error context information&#xA;and return it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;return errCustom{&#xA;    message: &amp;quot;whoops&amp;quot;,&#xA;    code:    500&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;function-types&#34;&gt;Function Types&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Foo func(int, string)&#xA;&#xA;func (f Foo) Bar(s string) {&#xA;  fmt.Printf(&amp;quot;s: %s\n&amp;quot;, s)&#xA;}&#xA;&#xA;func FooIt(x int, y string) {&#xA;  fmt.Printf(&amp;quot;x: %d - y: %s\n&amp;quot;, x, y)&#xA;}&#xA;&#xA;// We HAVE to define the incoming type of &amp;quot;fn&amp;quot;&#xA;// Which in this case is a Foo type&#xA;func TestIt(fn Foo) {&#xA;  fn(99, &amp;quot;problems&amp;quot;)&#xA;}&#xA;&#xA;// We could do this without defining a func type&#xA;// But as you can see, this is a bit ugly&#xA;// Plus if we need this function passed around a lot&#xA;// then it means a lot of duplicated effort &#xA;// typing the signature over and over&#xA;func TestItManually(fn func(int, string)) {&#xA;  fn(100, &amp;quot;problems&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;  // Here we&#39;re just demonstrating passing around the FooIt function&#xA;  // It demonstrates first-class function support in Go&#xA;  // But also that we can ensure the function passed around has the expected signature&#xA;  TestIt(FooIt)&#xA;  TestItManually(FooIt)&#xA;  &#xA;  x := Foo(FooIt) // Convert our function into a Foo type&#xA;  x(0, &amp;quot;hai&amp;quot;)     // Now we can execute it as we would FooIt itself&#xA;  &#xA;  FooIt(1, &amp;quot;bye&amp;quot;)&#xA;  &#xA;  // Notice the types are different&#xA;  // FooIt is just a function with a signature (no known type associated with it)&#xA;  // Whereas &amp;quot;x&amp;quot; is of known type &amp;quot;Foo&amp;quot;&#xA;  fmt.Printf(&amp;quot;%T\n&amp;quot;, FooIt) // func(int, string)&#xA;  fmt.Printf(&amp;quot;%T\n&amp;quot;, x)     // main.Foo&#xA;  &#xA;  // But we&#39;ll see that the function &amp;quot;x&amp;quot; &#xA;  // which was converted into a Foo type&#xA;  // now has access to a Bar method&#xA;  // Although FooIt has a matching signature, it&#39;s not a Foo type&#xA;  // and so it doesn&#39;t have a Bar method available&#xA;  x.Bar(&amp;quot;we have a Bar method&amp;quot;)&#xA;  &#xA;  // We can&#39;t even execute:&#xA;  // FooIt.Bar(&amp;quot;we don&#39;t have a Bar method&amp;quot;)&#xA;  // Because the compiler will stop us&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;enumerator-iota&#34;&gt;Enumerator IOTA&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Within a constant declaration, the predeclared identifier &lt;code&gt;iota&lt;/code&gt; represents&#xA;successive untyped integer constants. It is reset to 0 whenever the reserved&#xA;word &lt;code&gt;const&lt;/code&gt; appears in the source.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;const (&#xA;  foo = iota // 0&#xA;  bar&#xA;  _ // skip this value&#xA;  baz&#xA;)&#xA;&#xA;const (&#xA;  beep = iota // 0 (reset)&#xA;  boop&#xA;)&#xA;&#xA;func main() {&#xA;  fmt.Println(foo, bar, baz) // 0 1 3&#xA;  fmt.Println(beep, boop)    // 0 1&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;struct-var-vs-type&#34;&gt;Struct: Var vs Type&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A variable of Struct type doesn&amp;rsquo;t need to be instantiated like a type struct:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;var data struct {&#xA;  A string&#xA;  B string&#xA;}&#xA;&#xA;type data2 struct {&#xA;  A string&#xA;  B string&#xA;}&#xA;&#xA;func main() {&#xA;  data.A = &amp;quot;Hai&amp;quot;&#xA;  data.B = &amp;quot;Bai&amp;quot;&#xA;  &#xA;  fmt.Printf(&#xA;    &amp;quot;%#v, %+v, %+v&amp;quot;, &#xA;    data.A, &#xA;    data.B, &#xA;    data2{A: &amp;quot;abc&amp;quot;, B: &amp;quot;def&amp;quot;}&#xA;  )&#xA;  // &amp;quot;Hai&amp;quot;, Bai, {A:abc B:def}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;embedded-structs&#34;&gt;Embedded Structs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The first example demonstrates a &amp;lsquo;named&amp;rsquo; field utilising an embedded Struct:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Point struct {&#xA;  X, Y int&#xA;}&#xA;&#xA;type Circle struct {&#xA;  Center Point // named embeded field&#xA;  Radius int&#xA;}&#xA;&#xA;type Wheel struct {&#xA;  Circle Circle // named embeded field&#xA;  Spokes int&#xA;}&#xA;&#xA;func main() {&#xA;  var w Wheel&#xA;  w.Circle.Center.X = 8&#xA;  w.Circle.Center.Y = 8&#xA;  w.Circle.Radius = 5&#xA;  w.Spokes = 20&#xA;&#xA;  fmt.Printf(&amp;quot;%+v&amp;quot;, w)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which prints:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{Circle:{Center:{X:8 Y:8} Radius:5} Spokes:20}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The second example demonstrates an &amp;lsquo;anonymous&amp;rsquo; field instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Point struct {&#xA;  X, Y int&#xA;}&#xA;&#xA;type Circle struct {&#xA;  Point&#xA;  Radius int&#xA;}&#xA;&#xA;type Wheel struct {&#xA;  Circle&#xA;  Spokes int&#xA;}&#xA;&#xA;func main() {&#xA;  var w Wheel&#xA;  w.X = 8       // w.Circle.Point.X&#xA;  w.Y = 8       // w.Circle.Point.Y&#xA;  w.Radius = 5  // w.Circle.Radius&#xA;  w.Spokes = 20&#xA;&#xA;  fmt.Printf(&amp;quot;%+v&amp;quot;, w)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which prints:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{Circle:{Point:{X:8 Y:8} Radius:5} Spokes:20}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;anonymous fields don&amp;rsquo;t work shorthand literal Struct&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how methods of a composited object can be&#xA;accessed from the consuming object:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Point struct {&#xA;  X, Y int&#xA;}&#xA;&#xA;func (p Point) foo() {&#xA;  fmt.Printf(&amp;quot;foo: %+v\n&amp;quot;, p)&#xA;}&#xA;&#xA;type Circle struct {&#xA;  Point&#xA;  Radius int&#xA;}&#xA;&#xA;type Wheel struct {&#xA;  Circle&#xA;  Spokes int&#xA;}&#xA;&#xA;func main() {&#xA;  var w Wheel&#xA;  w.X = 8      // w.Circle.Point.X&#xA;  w.Y = 8      // w.Circle.Point.Y&#xA;  w.foo()      // w.Circle.Point.foo()&#xA;  w.Radius = 5 // w.Circle.Radius&#xA;  w.Spokes = 20&#xA;&#xA;  fmt.Printf(&amp;quot;%+v&amp;quot;, w)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which prints:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo: {X:8 Y:8}&#xA;{Circle:{Point:{X:8 Y:8} Radius:5} Spokes:20}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following example shows how you can mix and match &amp;lsquo;named&amp;rsquo; and &amp;lsquo;anonymous&amp;rsquo; embeds:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;// Point is ...&#xA;type Point struct {&#xA;    X, Y int&#xA;}&#xA;&#xA;func (p Point) foo() {&#xA;    fmt.Printf(&amp;quot;foo: %+v\n&amp;quot;, p)&#xA;}&#xA;&#xA;// Circle is ...&#xA;type Circle struct {&#xA;    p      Point&#xA;    Radius int&#xA;}&#xA;&#xA;// Wheel is ...&#xA;type Wheel struct {&#xA;    Circle&#xA;    Spokes int&#xA;}&#xA;&#xA;func main() {&#xA;    var w Wheel&#xA;    w.Spokes = 1&#xA;    w.Radius = 2&#xA;    w.p.X = 3 // w.Circle.p.X&#xA;    w.p.Y = 4 // w.Circle.p.X&#xA;    w.p.foo()&#xA;    fmt.Printf(&amp;quot;%+v&amp;quot;, w)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a more practical example that demonstrates how embedded functionality&#xA;can make code more expressive:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;sync&amp;quot;&#xA;)&#xA;&#xA;// Anonymous struct&#xA;var cache = struct {&#xA;  sync.Mutex&#xA;  mapping map[string]string&#xA;}{&#xA;  mapping: make(map[string]string), // initial zero value for map&#xA;}&#xA;&#xA;func setValue() {&#xA;  cache.Lock()&#xA;  cache.mapping[&amp;quot;foo&amp;quot;] = &amp;quot;bar&amp;quot;&#xA;  cache.Unlock()&#xA;}&#xA;&#xA;func main() {&#xA;  setValue()&#xA;&#xA;  cache.Lock()&#xA;  v := cache.mapping[&amp;quot;foo&amp;quot;]&#xA;  cache.Unlock()&#xA;&#xA;  fmt.Printf(&amp;quot;v: %s&amp;quot;, v)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;reference-vs-value&#34;&gt;Reference vs Value&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Summary: limit passing by reference unless the size of the copied value is a&#xA;problem (i.e. memory allocations).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Map data structures are passed by reference, rather than a copied value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;  m := make(map[string]int)&#xA;  fmt.Println(&amp;quot;main before, m = &amp;quot;, m)&#xA;  foo(m)&#xA;  fmt.Println(&amp;quot;main after, m = &amp;quot;, m)&#xA;}&#xA;&#xA;func foo(m map[string]int) {&#xA;  fmt.Println(&amp;quot;foo before, m = &amp;quot;, m)&#xA;  m[&amp;quot;hai&amp;quot;] = 123&#xA;  fmt.Println(&amp;quot;foo after, m = &amp;quot;, m)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;main before, m =  map[]&#xA;foo before, m =  map[]&#xA;foo after, m =  map[hai:123]&#xA;main after, m =  map[hai:123]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how the map is mutated even once the &lt;code&gt;foo&lt;/code&gt; function has finished. This is&#xA;because a reference to the underlying struct memory location was passed and so&#xA;the changes made were effective everywhere.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In fact, anything with &lt;code&gt;make&lt;/code&gt; is a reference, as well as any explicit interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now consider the next example, which is a slice of integers:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;    m := []int{1, 2, 3}&#xA;    fmt.Println(&amp;quot;main before, m = &amp;quot;, m)&#xA;    foo(m)&#xA;    fmt.Println(&amp;quot;main after, m = &amp;quot;, m)&#xA;}&#xA;&#xA;func foo(m []int) {&#xA;    fmt.Println(&amp;quot;foo before, m = &amp;quot;, m)&#xA;    m = append(m, 4)&#xA;    fmt.Println(&amp;quot;foo after, m = &amp;quot;, m)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;main before, m =  [1 2 3]&#xA;foo before, m =  [1 2 3]&#xA;foo after, m =  [1 2 3 4]&#xA;main after, m =  [1 2 3]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how the slice isn&amp;rsquo;t showing as mutated after the &lt;code&gt;foo&lt;/code&gt; function has&#xA;finished. This is because a &lt;em&gt;copy&lt;/em&gt; of the slice was passed to the function for&#xA;mutating.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example we pass a struct by value (i.e. a copy of the &lt;code&gt;person&lt;/code&gt;&#xA;variable is passed):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Person struct {&#xA;    firstName string&#xA;    lastName  string&#xA;}&#xA;&#xA;func changeName(p Person) {&#xA;    p.firstName = &amp;quot;Bob&amp;quot;&#xA;}&#xA;&#xA;func main() {&#xA;    person := Person {&#xA;        firstName: &amp;quot;Alice&amp;quot;,&#xA;        lastName: &amp;quot;Dow&amp;quot;,&#xA;    }&#xA;&#xA;    changeName(person)&#xA;&#xA;    fmt.Println(person)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In order to have that type of change we would need to pass a pointer reference:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Person struct {&#xA;    firstName string&#xA;    lastName  string&#xA;}&#xA;&#xA;func changeName(p *Person) {&#xA;    p.firstName = &amp;quot;Bob&amp;quot;&#xA;}&#xA;&#xA;func main() {&#xA;    person := Person {&#xA;        firstName: &amp;quot;Alice&amp;quot;,&#xA;        lastName: &amp;quot;Dow&amp;quot;,&#xA;    }&#xA;&#xA;    changeName(&amp;amp;person)&#xA;&#xA;    fmt.Println(person)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;see-all-methods-on-type&#34;&gt;See all methods on &lt;code&gt;&amp;lt;Type&amp;gt;&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;errType := reflect.TypeOf(err)&#xA;for i := 0; i &amp;lt; errType.NumMethod(); i++ {&#xA;  method := errType.Method(i)&#xA;  fmt.Println(method.Name)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;convert-struct-into-json&#34;&gt;Convert Struct into JSON&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;encoding/json&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  type Message struct {&#xA;    Sequence  int    `json:&amp;quot;sequence&amp;quot;`&#xA;    Title     string `json:&amp;quot;title&amp;quot;`&#xA;    Timestamp time.Time   `json:&amp;quot;timestamp&amp;quot;`&#xA;  }&#xA;  msg := Message{1, &amp;quot;Foobar&amp;quot;, time.Now()}&#xA;  b, err := json.Marshal(msg)&#xA;  if err != nil {&#xA;    fmt.Println(&amp;quot;error:&amp;quot;, err)&#xA;  }&#xA;  os.Stdout.Write(b)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;pretty-printing-json-string&#34;&gt;Pretty Printing JSON String&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;encoding/json&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  type ColorGroup struct {&#xA;    ID     int&#xA;    Name   string&#xA;    Colors []string&#xA;  }&#xA;  group := ColorGroup{&#xA;    ID:     1,&#xA;    Name:   &amp;quot;Reds&amp;quot;,&#xA;    Colors: []string{&amp;quot;Crimson&amp;quot;, &amp;quot;Red&amp;quot;, &amp;quot;Ruby&amp;quot;, &amp;quot;Maroon&amp;quot;},&#xA;  }&#xA;  b, err := json.MarshalIndent(group, &amp;quot;&amp;quot;, &amp;quot;    &amp;quot;)&#xA;  if err != nil {&#xA;    fmt.Println(&amp;quot;error:&amp;quot;, err)&#xA;  }&#xA;  os.Stdout.Write(b)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;convert-struct-into-yaml&#34;&gt;Convert Struct into YAML&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;&#xA;  &amp;quot;gopkg.in/yaml.v2&amp;quot;&#xA;)&#xA;&#xA;type ComponentYaml struct {&#xA;  Id  string `yaml:&amp;quot;id&amp;quot;`&#xA;  Url string `yaml:&amp;quot;url&amp;quot;`&#xA;}&#xA;&#xA;type ComponentsYamlList struct {&#xA;  Components []ComponentYaml `yaml:&amp;quot;components&amp;quot;`&#xA;}&#xA;&#xA;func main() {&#xA;  var y ComponentsYamlList&#xA;&#xA;  yaml.Unmarshal([]byte(&#xA;    &amp;quot;components:&#xA;    \n  - id: google&#xA;    \n    url: http://google.com&#xA;    \n  - id: integralist&#xA;    \n    url: http://integralist.co.uk&amp;quot;), &amp;amp;y)&#xA;&#xA;  fmt.Println(y)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;unknown-yaml-structure&#34;&gt;Unknown YAML Structure&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;encoding/json&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;&#xA;  &amp;quot;gopkg.in/yaml.v2&amp;quot;&#xA;)&#xA;&#xA;var yml = []byte(`&#xA;- key: foo&#xA;  value: bar&#xA;  secret: false&#xA;- key: beep&#xA;  value: boop&#xA;  secret: true&#xA;`)&#xA;&#xA;type Data struct {&#xA;  Items []map[string]interface{}&#xA;}&#xA;&#xA;func main() {&#xA;  y := []map[string]interface{}{}&#xA;&#xA;  if err := yaml.Unmarshal(yml, &amp;amp;y); err == nil {&#xA;    fmt.Printf(&amp;quot;%#v\n&amp;quot;, y)&#xA;  } else {&#xA;    fmt.Println(err.Error())&#xA;  }&#xA;&#xA;  myYaml := Data{Items: y}&#xA;&#xA;  json.NewEncoder(os.Stdout).Encode(myYaml.Items)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;sorting-structs&#34;&gt;Sorting Structs&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;sort&amp;quot;&#xA;)&#xA;&#xA;type vals []Value&#xA;&#xA;type Value struct {&#xA;  Key string&#xA;  Value string&#xA;  Secure bool&#xA;}&#xA;&#xA;// Satisfy the Sort interface&#xA;func (v vals) Len() int      { return len(v) }&#xA;func (v vals) Swap(i, j int) { v[i], v[j] = v[j], v[i] }&#xA;func (v vals) Less(i, j int) bool { &#xA;  return v[i].Key &amp;lt; v[j].Key &#xA;}&#xA;&#xA;func main() {&#xA;  orig := vals{&#xA;    {&amp;quot;CK&amp;quot;, &amp;quot;BV&amp;quot;, false},&#xA;    {&amp;quot;DK&amp;quot;, &amp;quot;AV&amp;quot;, true},&#xA;    {&amp;quot;AK&amp;quot;, &amp;quot;CV&amp;quot;, false},&#xA;    {&amp;quot;BK&amp;quot;, &amp;quot;DV&amp;quot;, true},&#xA;  }&#xA;  &#xA;  fmt.Printf(&amp;quot;%+v\n\n&amp;quot;, orig)&#xA;  sort.Sort(orig)&#xA;  fmt.Printf(&amp;quot;%+v\n\n&amp;quot;, orig)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a similar version that sorts by name and age:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;sort&amp;quot;&#xA;)&#xA;&#xA;type person struct {&#xA;  Name string&#xA;  Age  int&#xA;}&#xA;&#xA;type byName []person&#xA;&#xA;func (p byName) Len() int {&#xA;  return len(p)&#xA;}&#xA;func (p byName) Less(i, j int) bool {&#xA;  return p[i].Name &amp;lt; p[j].Name&#xA;}&#xA;func (p byName) Swap(i, j int) {&#xA;  p[i], p[j] = p[j], p[i]&#xA;}&#xA;&#xA;type byAge []person&#xA;&#xA;func (p byAge) Len() int {&#xA;  return len(p)&#xA;}&#xA;func (p byAge) Less(i, j int) bool {&#xA;  return p[i].Age &amp;lt; p[j].Age&#xA;}&#xA;func (p byAge) Swap(i, j int) {&#xA;  p[i], p[j] = p[j], p[i]&#xA;}&#xA;&#xA;func main() {&#xA;  kids := []person{&#xA;    {&amp;quot;Jill&amp;quot;, 9},&#xA;    {&amp;quot;Jack&amp;quot;, 10},&#xA;  }&#xA;&#xA;  sort.Sort(byName(kids))&#xA;  fmt.Println(kids)&#xA;&#xA;  sort.Sort(byAge(kids))&#xA;  fmt.Println(kids)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which results in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[{Jack 10} {Jill 9}]&#xA;[{Jill 9} {Jack 10}]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;read-users-input&#34;&gt;Read Users Input&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;reader := bufio.NewReader(os.Stdin)&#xA;fmt.Print(&amp;quot;Enter text: &amp;quot;)&#xA;text, _ := reader.ReadString(&#39;\n&#39;)&#xA;fmt.Println(text)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;http-middleware&#34;&gt;HTTP Middleware&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This code was modified from&#xA;&lt;a href=&#34;https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81&#34; target=&#34;_blank&#34;&gt;@matryer&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;type data struct {&#xA;  Greeting string&#xA;  Punct    string&#xA;  Who      string&#xA;}&#xA;&#xA;func (s data) ServeHTTP(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprint(w, s.Greeting, s.Punct, s.Who)&#xA;}&#xA;&#xA;type adapter func(http.Handler) http.Handler&#xA;&#xA;func adapt(h http.Handler, adapters ...adapter) http.Handler {&#xA;  // Ideally you&#39;d do this in reverse&#xA;  // to ensure the order of the middleware&#xA;  // matches their specified order&#xA;  for _, adapter := range adapters {&#xA;    h = adapter(h)&#xA;  }&#xA;  return h&#xA;}&#xA;&#xA;func notify(logger *log.Logger) adapter {&#xA;  return func(h http.Handler) http.Handler {&#xA;    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;      logger.Println(&amp;quot;before&amp;quot;)&#xA;      defer logger.Println(&amp;quot;after&amp;quot;)&#xA;      h.ServeHTTP(w, r)&#xA;    })&#xA;  }&#xA;}&#xA;&#xA;func doSomething() adapter {&#xA;  return func(h http.Handler) http.Handler {&#xA;    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;      fmt.Println(&amp;quot;before&amp;quot;)&#xA;      defer fmt.Println(&amp;quot;after&amp;quot;)&#xA;      h.ServeHTTP(w, r)&#xA;    })&#xA;  }&#xA;}&#xA;&#xA;func main() {&#xA;  http.Handle(&amp;quot;/hello&amp;quot;, &amp;amp;data{&amp;quot;Hello&amp;quot;, &amp;quot; &amp;quot;, &amp;quot;Gophers!&amp;quot;})&#xA;&#xA;  logger := log.New(os.Stdout, &amp;quot;server: &amp;quot;, log.Lshortfile)&#xA;&#xA;  http.Handle(&amp;quot;/hello-with-middleware&amp;quot;, adapt(&#xA;    &amp;amp;data{&amp;quot;Hello&amp;quot;, &amp;quot; &amp;quot;, &amp;quot;Gophers!&amp;quot;},&#xA;    notify(logger), // runs second&#xA;    doSomething(), // runs first&#xA;  ))&#xA;&#xA;  http.ListenAndServe(&amp;quot;localhost:4000&amp;quot;, nil)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This code will run a web server with two valid endpoints:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;/hello&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/hello-with-middleware&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The client sees the same output but the latter endpoint produces the following&#xA;stdout output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;before&#xA;server: middleware.go:35: before&#xA;server: middleware.go:38: after&#xA;after&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;sessions&#34;&gt;Sessions&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;const cookiePrefix = &amp;quot;integralist-example-cookie-&amp;quot;&#xA;&#xA;func main() {&#xA;  http.HandleFunc(&amp;quot;/&amp;quot;, login)&#xA;  http.HandleFunc(&amp;quot;/admin&amp;quot;, admin)&#xA;  http.HandleFunc(&amp;quot;/logout&amp;quot;, logout)&#xA;  http.ListenAndServe(&amp;quot;localhost:4000&amp;quot;, nil)&#xA;}&#xA;&#xA;func login(w http.ResponseWriter, r *http.Request) {&#xA;  if r.Method == &amp;quot;GET&amp;quot; {&#xA;    fmt.Fprintf(w, `&#xA;&amp;lt;html&amp;gt;&#xA;  &amp;lt;body&amp;gt;&#xA;    &amp;lt;form method=&amp;quot;POST&amp;quot;&amp;gt;&#xA;      Username: &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;username&amp;quot;&amp;gt;&#xA;      &amp;lt;br /&amp;gt;&#xA;      Password: &amp;lt;input type=&amp;quot;password&amp;quot; name=&amp;quot;password&amp;quot;&amp;gt;&#xA;      &amp;lt;br /&amp;gt;&#xA;      &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Login&amp;quot;&amp;gt;&#xA;  &amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;`)&#xA;  }&#xA;&#xA;  if r.Method == &amp;quot;POST&amp;quot; {&#xA;    username := r.FormValue(&amp;quot;username&amp;quot;)&#xA;    password := r.FormValue(&amp;quot;password&amp;quot;)&#xA;&#xA;    if username == &amp;quot;admin&amp;quot; &amp;amp;&amp;amp; password == &amp;quot;password&amp;quot; {&#xA;      http.SetCookie(w, &amp;amp;http.Cookie{&#xA;        Name:  cookiePrefix + &amp;quot;user&amp;quot;,&#xA;        Value: username,&#xA;      })&#xA;      http.Redirect(w, r, &amp;quot;/admin&amp;quot;, 302)&#xA;    } else {&#xA;      fmt.Fprintf(w, `&#xA;&amp;lt;html&amp;gt;&#xA;  &amp;lt;body&amp;gt;&#xA;    Login details were incorrect. Sorry, &amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;try again&amp;lt;/a&amp;gt;&#xA;  &amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;`)&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;func logout(w http.ResponseWriter, r *http.Request) {&#xA;  http.SetCookie(w, &amp;amp;http.Cookie{&#xA;    Name:    cookiePrefix + &amp;quot;user&amp;quot;,&#xA;    Value:   &amp;quot;&amp;quot;,&#xA;    Expires: time.Now(),&#xA;  })&#xA;&#xA;  http.Redirect(w, r, &amp;quot;/&amp;quot;, 302)&#xA;}&#xA;&#xA;func admin(w http.ResponseWriter, r *http.Request) {&#xA;  cookie, err := r.Cookie(cookiePrefix + &amp;quot;user&amp;quot;)&#xA;  if err != nil {&#xA;    http.Redirect(w, r, &amp;quot;/&amp;quot;, 401) // Unauthorized&#xA;    return&#xA;  }&#xA;&#xA;  fmt.Fprintf(w, `&#xA;&amp;lt;html&amp;gt;&#xA;  &amp;lt;body&amp;gt;&#xA;    Logged into admin area as: %s&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#xA;    &amp;lt;a href=&amp;quot;/logout&amp;quot;&amp;gt;Logout&amp;lt;/a&amp;gt;&#xA;  &amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;`, cookie.Value)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;https-tls-request&#34;&gt;HTTPS TLS Request&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package requester&#xA;&#xA;import (&#xA;  &amp;quot;crypto/tls&amp;quot;&#xA;  &amp;quot;crypto/x509&amp;quot;&#xA;  &amp;quot;flag&amp;quot;&#xA;  &amp;quot;io/ioutil&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;var (&#xA;  certFile = flag.String(&#xA;    &amp;quot;cert&amp;quot;, &amp;quot;/etc/pki/tls/certs/client.crt&amp;quot;, &amp;quot;A PEM eoncoded certificate file.&amp;quot;&#xA;  )&#xA;  keyFile  = flag.String(&#xA;    &amp;quot;key&amp;quot;, &amp;quot;/etc/pki/tls/private/client.key&amp;quot;, &amp;quot;A PEM encoded private key file.&amp;quot;&#xA;  )&#xA;  caFile   = flag.String(&#xA;    &amp;quot;CA&amp;quot;, &amp;quot;/etc/ca/cloud-ca.pem&amp;quot;, &amp;quot;A PEM eoncoded CA&#39;s certificate file.&amp;quot;&#xA;  )&#xA;)&#xA;&#xA;func SecureClient() *http.Client {&#xA;  // Load client cert&#xA;  cert, err := tls.LoadX509KeyPair(*certFile, *keyFile)&#xA;  if err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;&#xA;  // Load CA cert&#xA;  caCert, err := ioutil.ReadFile(*caFile)&#xA;  if err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;  caCertPool := x509.NewCertPool()&#xA;  caCertPool.AppendCertsFromPEM(caCert)&#xA;&#xA;  // Setup HTTPS client&#xA;  tlsConfig := &amp;amp;tls.Config{&#xA;    Certificates:       []tls.Certificate{cert},&#xA;    RootCAs:            caCertPool,&#xA;    InsecureSkipVerify: true,&#xA;  }&#xA;  tlsConfig.BuildNameToCertificate()&#xA;  transport := &amp;amp;http.Transport{TLSClientConfig: tlsConfig}&#xA;  client := &amp;amp;http.Client{Transport: transport}&#xA;&#xA;  return client&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;And to use it&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;client := requester.SecureClient()&#xA;&#xA;// GET&#xA;resp, err := client.Get(someEndpoint)&#xA;&#xA;// POST&#xA;req, err := http.NewRequest(&amp;quot;POST&amp;quot;, someEndpoint, bytes.NewBuffer(jsonStr))&#xA;req.Header.Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/json&amp;quot;)&#xA;resp, err := client.Do(req)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;http-get-web-page&#34;&gt;HTTP GET Web Page&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;io/ioutil&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  response, err := http.Get(&amp;quot;http://www.integralist.co.uk/&amp;quot;)&#xA;  if err != nil {&#xA;    fmt.Println(err.Error())&#xA;    os.Exit(1)&#xA;  }&#xA;&#xA;  defer response.Body.Close()&#xA;&#xA;  contents, err := ioutil.ReadAll(response.Body)&#xA;  if err != nil {&#xA;    fmt.Println(err.Error())&#xA;    os.Exit(1)&#xA;  }&#xA;&#xA;  fmt.Println(string(contents))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t use this ☝️ as it has timeout set to infinity by default&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Safer option is to create your own http.Client struct&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;os&amp;quot;&#xA;    &amp;quot;sync&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func defaultClient(wg *sync.WaitGroup) {&#xA;    // http.Get calls http.DefaultClient&#xA;    // https://golang.org/src/net/http/client.go?s=12086:12134#L359&#xA;    // https://golang.org/pkg/net/http/#Client&#xA;    response, err := http.Get(&amp;quot;https://www.integralist.co.uk/&amp;quot;)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    defer response.Body.Close()&#xA;&#xA;    contents, err := ioutil.ReadAll(response.Body)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    fmt.Println(&amp;quot;\ndefaultClient...&amp;quot;)&#xA;    fmt.Println(response.Status)&#xA;    fmt.Println(string(contents[0:10]))&#xA;&#xA;    wg.Done()&#xA;}&#xA;&#xA;func customClient(wg *sync.WaitGroup) {&#xA;    var netClient = &amp;amp;http.Client{&#xA;        Timeout: time.Second * 10,&#xA;    }&#xA;    response, err := netClient.Get(&amp;quot;https://www.integralist.co.uk/&amp;quot;)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    defer response.Body.Close()&#xA;&#xA;    contents, err := ioutil.ReadAll(response.Body)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    fmt.Println(&amp;quot;\ncustomClient...&amp;quot;)&#xA;    fmt.Println(response.Status)&#xA;    fmt.Println(string(contents[0:10]))&#xA;&#xA;    wg.Done()&#xA;}&#xA;&#xA;func customTransport(wg *sync.WaitGroup) {&#xA;    var netTransport = &amp;amp;http.Transport{&#xA;        Dial: (&amp;amp;net.Dialer{&#xA;            Timeout: 5 * time.Second,&#xA;        }).Dial,&#xA;        TLSHandshakeTimeout: 5 * time.Second,&#xA;    }&#xA;&#xA;    var netClient = &amp;amp;http.Client{&#xA;        Timeout:   time.Second * 10,&#xA;        Transport: netTransport,&#xA;    }&#xA;&#xA;    response, err := netClient.Get(&amp;quot;https://www.integralist.co.uk/&amp;quot;)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    defer response.Body.Close()&#xA;&#xA;    contents, err := ioutil.ReadAll(response.Body)&#xA;    if err != nil {&#xA;        fmt.Println(err.Error())&#xA;        os.Exit(1)&#xA;    }&#xA;&#xA;    fmt.Println(&amp;quot;\ncustomTransport...&amp;quot;)&#xA;    fmt.Println(response.Status)&#xA;    fmt.Println(string(contents[0:10]))&#xA;&#xA;    wg.Done()&#xA;}&#xA;&#xA;func main() {&#xA;    var wg sync.WaitGroup&#xA;    wg.Add(3)&#xA;    go defaultClient(&amp;amp;wg)&#xA;    go customClient(&amp;amp;wg)&#xA;    go customTransport(&amp;amp;wg)&#xA;    wg.Wait()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;custom-http-request-methods&#34;&gt;Custom HTTP Request Methods&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go doesn&amp;rsquo;t provide abstractions for all the various HTTP request types, so for&#xA;things like &lt;code&gt;PUT&lt;/code&gt; you have to implement it yourself. The following is an example&#xA;that creates a secure (TLS/HTTPS) &lt;code&gt;PUT&lt;/code&gt; abstraction&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func SecurePut(url, contentType string, configFile io.Reader) (*http.Response, error) {&#xA;  client := &amp;amp;http.Client{Transport: configureTLS()}&#xA;  req, err := http.NewRequest(&amp;quot;PUT&amp;quot;, url, configFile)&#xA;  if err != nil {&#xA;    return nil, err&#xA;  }&#xA;  req.Header.Add(&amp;quot;Content-Type&amp;quot;, contentType)&#xA;  resp, err := client.Do(req)&#xA;&#xA;  return resp, err&#xA;}&#xA;&#xA;func configureTLS() *http.Transport {&#xA;  certFilePath := &amp;quot;path/to/cert&amp;quot;&#xA;  keyFilePath := &amp;quot;path/to/privateKey&amp;quot;&#xA;  caPath := &amp;quot;path/to/ca&amp;quot;&#xA;&#xA;  // Load client cert&#xA;  cert, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)&#xA;  if err != nil {&#xA;    msg := fmt.Sprintf(&amp;quot;Error loading developer cert, path: \&amp;quot;%s\&amp;quot;&amp;quot;, certFilePath)&#xA;    output.Error(msg)&#xA;  }&#xA;&#xA;  // Load CA cert&#xA;  caCert, err := ioutil.ReadFile(caPath)&#xA;  if err != nil {&#xA;    msg := fmt.Sprintf(&amp;quot;Error loading CA cert, path: \&amp;quot;%s\&amp;quot;&amp;quot;, caPath)&#xA;    output.Error(msg)&#xA;  }&#xA;  caCertPool := x509.NewCertPool()&#xA;  caCertPool.AppendCertsFromPEM(caCert)&#xA;&#xA;  // Setup HTTPS client&#xA;  tlsConfig := &amp;amp;tls.Config{&#xA;    Certificates:       []tls.Certificate{cert},&#xA;    RootCAs:            caCertPool,&#xA;    InsecureSkipVerify: true,&#xA;  }&#xA;  tlsConfig.BuildNameToCertificate()&#xA;&#xA;  return &amp;amp;http.Transport{TLSClientConfig: tlsConfig}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;pointers&#34;&gt;Pointers&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;// Point stores co-ordinates&#xA;type Point struct {&#xA;  x int&#xA;  y int&#xA;}&#xA;&#xA;// If receiver (Point) isn&#39;t set to a pointer (*Point) &#xA;// then the struct&#39;s field value won&#39;t be updated outside the method&#xA;func (p *Point) scaleBy(factor int) {&#xA;  fmt.Printf(&amp;quot;scaleBy (before modification): %+v\n&amp;quot;, p)&#xA;&#xA;  // Don&#39;t need to derefence (*) struct fields&#xA;  // Compiler will perform an implicit &amp;amp;p for you&#xA;  // You only need to dereference in standard functions &#xA;  // when a argument pointer is required (see below Array Pointer example)&#xA;  p.x *= factor&#xA;  p.y *= factor&#xA;&#xA;  fmt.Printf(&amp;quot;scaleBy (after modification): %+v\n&amp;quot;, p)&#xA;}&#xA;&#xA;func main() {&#xA;  // Doesn&#39;t matter if we do or don&#39;t get the address space (&amp;amp;) for foo/bar&#39;s Point&#xA;  foo := &amp;amp;Point{1, 2}&#xA;  bar := &amp;amp;Point{6, 8}&#xA;&#xA;  fmt.Printf(&amp;quot;Main foo.x: %+v\n&amp;quot;, foo.x)&#xA;  fmt.Printf(&amp;quot;Main bar.x: %+v\n&amp;quot;, bar.x)&#xA;&#xA;  foo.scaleBy(5)&#xA;  bar.scaleBy(5)&#xA;&#xA;  fmt.Printf(&amp;quot;Main foo.x: %+v\n&amp;quot;, foo.x)&#xA;  fmt.Printf(&amp;quot;Main foo.y: %+v\n&amp;quot;, foo.y)&#xA;&#xA;  fmt.Printf(&amp;quot;Main bar.x: %+v\n&amp;quot;, bar.x)&#xA;  fmt.Printf(&amp;quot;Main bar.y: %+v\n&amp;quot;, bar.y)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;compiler can only apply implicit dereference for variables and struct&#xA;fields. This wouldn&amp;rsquo;t work &lt;code&gt;Point{1, 2}.scaleBy(5)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Results in the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Main foo.x: 1&#xA;Main bar.x: 6&#xA;scaleBy (before modification): &amp;amp;{x:1 y:2}&#xA;scaleBy (after modification): &amp;amp;{x:5 y:10}&#xA;scaleBy (before modification): &amp;amp;{x:6 y:8}&#xA;scaleBy (after modification): &amp;amp;{x:30 y:40}&#xA;Main foo.x: 5&#xA;Main foo.y: 10&#xA;Main bar.x: 30&#xA;Main bar.y: 40&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;array-pointer&#34;&gt;Array Pointer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Deference an Array pointer so you can mutate the original Array values:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {  &#xA;    x := [3]int{1,2,3}&#xA;&#xA;    func(arr *[3]int) {&#xA;        (*arr)[0] = 7&#xA;        fmt.Println(arr) //prints &amp;amp;[7 2 3]&#xA;    }(&amp;amp;x)&#xA;&#xA;    fmt.Println(x) //prints [7 2 3]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively you can utilise a Slice instead of an Array, as the slice &amp;lsquo;header&amp;rsquo;&#xA;already has a &amp;lsquo;pointer&amp;rsquo; to an underlying Array:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {  &#xA;    x := []int{1,2,3}&#xA;&#xA;    func(arr []int) {&#xA;        arr[0] = 7&#xA;        fmt.Println(arr) //prints [7 2 3]&#xA;    }(x)&#xA;&#xA;    fmt.Println(x) //prints [7 2 3]&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;mutating-values&#34;&gt;Mutating Values&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Compose string&#xA;&#xA;func (c *Compose) Details() string {&#xA;  *c = &amp;quot;beep boop&amp;quot;&#xA;  return fmt.Sprintf(&amp;quot;Here are your details: %v&amp;quot;, *c)&#xA;}&#xA;&#xA;func main() {&#xA;  var c Compose&#xA;  c = &amp;quot;hai&amp;quot;&#xA;  fmt.Printf(&amp;quot;c: %+v\n&amp;quot;, c) // c&#xA;  fmt.Println(c.Details())&#xA;  fmt.Printf(&amp;quot;c: %+v\n&amp;quot;, c) // beep boop&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;type-assertion&#34;&gt;Type Assertion&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if e, ok := err.(net.Error); ok &amp;amp;&amp;amp; e.Timeout() {&#xA;  //&#xA;}&#xA;&#xA;type argError struct {&#xA;    arg  int&#xA;    prob string&#xA;}&#xA;&#xA;func (e *argError) Error() string {&#xA;    return fmt.Sprintf(&amp;quot;%d - %s&amp;quot;, e.arg, e.prob)&#xA;}&#xA;&#xA;if ae, ok := e.(*argError); ok {&#xA;  //&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;line-counting&#34;&gt;Line Counting&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Demonstrates how to use &lt;code&gt;bufio&lt;/code&gt; package to scan a file and read it line by line,&#xA;and then how to increment a map integer value using the shortcut &lt;code&gt;map[key]++&lt;/code&gt;.&#xA;Finally, demonstrates nested maps and ranging over them:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;bufio&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  counts := make(map[string]map[string]int)&#xA;  files := os.Args[1:]&#xA;  if len(files) == 0 {&#xA;    countLines(os.Stdin, &amp;quot;n/a&amp;quot;, counts)&#xA;  } else {&#xA;    for _, arg := range files {&#xA;      f, err := os.Open(arg)&#xA;      if err != nil {&#xA;        fmt.Fprintf(os.Stderr, &amp;quot;dup2: %v\n&amp;quot;, err)&#xA;        continue&#xA;      }&#xA;      countLines(f, arg, counts)&#xA;      f.Close()&#xA;    }&#xA;  }&#xA;  for key, nestedMap := range counts {&#xA;    fmt.Printf(&amp;quot;Text: %s\n&amp;quot;, key)&#xA;    for filename, count := range nestedMap {&#xA;      fmt.Printf(&amp;quot;\tFile: %s\n\tCount: %d\n&amp;quot;, filename, count)&#xA;    }&#xA;    fmt.Println(&amp;quot;&amp;quot;)&#xA;  }&#xA;}&#xA;&#xA;func countLines(f *os.File, filename string, counts map[string]map[string]int) {&#xA;  input := bufio.NewScanner(f)&#xA;  for input.Scan() {&#xA;    if val, ok := counts[input.Text()]; ok {&#xA;      val[filename]++&#xA;    } else {&#xA;      inner := make(map[string]int)&#xA;      inner[filename]++&#xA;      counts[input.Text()] = inner&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;reading-file-in-chunks&#34;&gt;Reading File in Chunks&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  // Create file (truncates file if it already exists)&#xA;  file, err := os.Create(&amp;quot;created.txt&amp;quot;)&#xA;  if err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;&#xA;  // Populate byte slice with some content&#xA;  b := make([]byte, 0)&#xA;  for i := 0; i &amp;lt; 5; i++ {&#xA;    b = append(b, &#39;!&#39;)&#xA;    b = append(b, &#39;\n&#39;)&#xA;    // notice single quotes for Rune rather than double quote for String&#xA;  }&#xA;  for i := 0; i &amp;lt; 5; i++ {&#xA;    b = append(b, &#39;?&#39;)&#xA;    b = append(b, &#39;\n&#39;)&#xA;    // notice single quotes for Rune rather than double quote for String&#xA;  }&#xA;  for i := 0; i &amp;lt; 5; i++ {&#xA;    b = append(b, &#39;%&#39;)&#xA;    b = append(b, &#39;\n&#39;)&#xA;    // notice single quotes for Rune rather than double quote for String&#xA;  }&#xA;&#xA;  // Write file contents&#xA;  bytesWritten, err := file.Write(b)&#xA;  if err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;  fmt.Printf(&amp;quot;Bytes written: %+v\n&amp;quot;, bytesWritten)&#xA;&#xA;  // Although getting the bytes written was useful for us&#xA;  // in this example, you might need to get total bytes&#xA;  // which can be done by copying file contents into dev/null&#xA;    // io.Copy(ioutil.Discard, resp.Body)&#xA;&#xA;  // Get current offset&#xA;  // 1st arg is how much to seek forward/backwards by&#xA;  // 2nd arg is relative to different settings&#xA;  //         0 == relative to start of file&#xA;  //         1 == current offset&#xA;  //         2 == relative to end of file&#xA;  currentOffset, err := file.Seek(0, 1)&#xA;  if err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;  fmt.Printf(&amp;quot;Current offset: %d\n&amp;quot;, currentOffset)&#xA;  file.Seek(-currentOffset, 1) // Return to start of file for next Read&#xA;&#xA;  // Read buffered view of file&#xA;  // create slice with underlying Array capacity set to total file bytes size&#xA;  data := make([]byte, 10, bytesWritten) &#xA;  eof := false&#xA;  for !eof {&#xA;    count, err := file.Read(data)&#xA;    if err != nil {&#xA;      eof = true&#xA;    }&#xA;    fmt.Printf(&amp;quot;read %d bytes: %q\n&amp;quot;, count, data[:count])&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;time&#34;&gt;Time&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;now := time.Now()&#xA;fmt.Println(now)&#xA;expiration := now.Add(time.Hour * 24 * 30)&#xA;fmt.Println(&amp;quot;Thirty days from now will be : &amp;quot;, expiration)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here we measure time:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;// Sleep requires a Duration&#xA;// time has set of constants we can use (lowest is 1 Duration)&#xA;// Second constant is an abstraction over the other constants&#xA;func main() {&#xA;  start := time.Now()&#xA;  time.Sleep(time.Duration(5) * time.Second) // sleep 5 seconds&#xA;  secs := time.Since(start).Seconds()&#xA;&#xA;  fmt.Printf(&amp;quot;Time spent: %f seconds&amp;quot;, secs)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a basic example that pauses execution of a channel until the timer has&#xA;expired (you would use this over a &lt;code&gt;timer.Sleep&lt;/code&gt; because you can cancel a timer&#xA;before it has expired):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  timer := time.NewTimer(time.Second * 2)&#xA;&#xA;  &amp;lt;-timer.C // pauses for two seconds&#xA;&#xA;  fmt.Println(&amp;quot;Timer expired&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Example of cancelling the timer:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  timer := time.NewTimer(time.Second * 2)&#xA;&#xA;  // Expensive process run in a separate thread&#xA;  go func() {&#xA;    &amp;lt;-timer.C&#xA;    fmt.Println(&amp;quot;Timer expired&amp;quot;)&#xA;  }()&#xA;&#xA;  stop := timer.Stop() // cancel the timer&#xA;  fmt.Println(stop)    // true&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can do a similar thing with Timers but in a different way:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  ticker := time.NewTicker(time.Millisecond * 500)&#xA;&#xA;  // Repetitive process&#xA;  go func() {&#xA;    // Range over the channel rather than pull from it&#xA;    for t := range ticker.C {&#xA;      fmt.Println(&amp;quot;Tick:&amp;quot;, t)&#xA;    }&#xA;  }()&#xA;&#xA;  // Stop ticker after three ticks/intervals&#xA;  time.Sleep(time.Millisecond * 1500)&#xA;  ticker.Stop()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can combine all these items together with a &lt;code&gt;select&lt;/code&gt; statement like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;time&amp;quot;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func main() {&#xA;  timeChan := time.NewTimer(time.Second).C&#xA;  tickChan := time.NewTicker(time.Millisecond * 400).C&#xA;&#xA;  // Used to signify we&#39;re done with this program&#xA;  doneChan := make(chan bool)&#xA;&#xA;  // Sleep for two seconds, then notify the channel we&#39;re done&#xA;  go func() {&#xA;    time.Sleep(time.Second * 2)&#xA;    doneChan &amp;lt;- true&#xA;  }()&#xA;&#xA;  for {&#xA;    select {&#xA;    case &amp;lt;-timeChan:&#xA;      fmt.Println(&amp;quot;Timer expired&amp;quot;)&#xA;    case &amp;lt;-tickChan:&#xA;      fmt.Println(&amp;quot;Ticker ticked&amp;quot;)&#xA;    case &amp;lt;-doneChan:&#xA;      fmt.Println(&amp;quot;Done&amp;quot;)&#xA;      return&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of this program would be something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Ticker ticked&#xA;Ticker ticked&#xA;Timer expired&#xA;Ticker ticked&#xA;Ticker ticked&#xA;Done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;starting-and-stopping-things-with-channels&#34;&gt;Starting and Stopping things with Channels&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I would imagine that for most cases you&amp;rsquo;ll want to use a &lt;code&gt;time.NewTimer&lt;/code&gt; as seen&#xA;in previous examples if you want to stop a goroutine that&amp;rsquo;s processing a long&#xA;running program. The following example is more for stopping a goroutine that&amp;rsquo;s&#xA;running code at a set interval (although using &lt;code&gt;time.NewTicker&lt;/code&gt; would probably&#xA;be more appropriate):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  quit := make(chan bool)&#xA;&#xA;  // Run a piece of code at a set interval&#xA;  go func() {&#xA;    for {&#xA;      select {&#xA;      case &amp;lt;-quit:&#xA;        return&#xA;      default:&#xA;        fmt.Println(&amp;quot;Not ready to stop this goroutine&amp;quot;)&#xA;        time.Sleep(time.Millisecond * 100)&#xA;      }&#xA;    }&#xA;  }()&#xA;&#xA;  // Do other stuff for two seconds&#xA;  time.Sleep(time.Second * 2)&#xA;&#xA;  // Quit goroutine&#xA;  quit &amp;lt;- true&#xA;&#xA;  fmt.Println(&amp;quot;Goroutine was stopped&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Starting a goroutine:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  // Use a struct type channel as it clarifies your intent&#xA;  // Which is this channel is used for &#39;signalling&#39;&#xA;  start := make(chan struct{})&#xA;&#xA;  for i := 0; i &amp;lt; 10000; i++ {&#xA;    go func() {&#xA;      &amp;lt;-start // wait for the start channel to be closed&#xA;      fmt.Println(&amp;quot;do stuff&amp;quot;)&#xA;    }()&#xA;  }&#xA;&#xA;  // at this point, all goroutines are ready to go&#xA;  // we just need to tell them to start by&#xA;  // closing the start channel&#xA;  close(start)&#xA;&#xA;  fmt.Println(&amp;quot;Let&#39;s pause briefly to give goroutines time to execute&amp;quot;)&#xA;&#xA;  time.Sleep(time.Millisecond * 10)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Stopping a goroutine:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  // Use a struct type channel as it clarifies your intent&#xA;  // Which is this channel is used for &#39;signalling&#39;&#xA;  done := make(chan struct{})&#xA;&#xA;  // Long running process put onto a thread&#xA;  go func() {&#xA;    fmt.Println(&amp;quot;Inside thread doing expensive processing&amp;quot;)&#xA;    time.Sleep(time.Second * 5)&#xA;    close(done)&#xA;  }()&#xA;&#xA;  fmt.Println(&amp;quot;Do other things&amp;quot;)&#xA;&#xA;  // Wait for long running process to finish&#xA;  &amp;lt;-done&#xA;&#xA;  fmt.Println(&amp;quot;Do more things&amp;quot;)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;channel-pipelines&#34;&gt;Channel Pipelines&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The principle of a pipeline, is to take data from one function and pass it into&#xA;another function, that receiving function will process the received data and&#xA;then that result is returned and subsequently passed onto another function&amp;hellip;&#xA;rinse and repeat for however long your pipeline needs to be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the below example (copied from&#xA;&lt;a href=&#34;https://blog.gopheracademy.com/advent-2015/automi-stream-processing-over-go-channels/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;)&#xA;demonstrates how a set of functions accept a channel and return a channel and so&#xA;channels is the &amp;lsquo;data&amp;rsquo; that is passed around the pipeline functions:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;import &amp;quot;sync&amp;quot;&#xA;&#xA;func ingest() &amp;lt;-chan []string {&#xA;  out := make(chan []string)&#xA;  go func() {&#xA;    out &amp;lt;- []string{&amp;quot;aaaa&amp;quot;, &amp;quot;bbb&amp;quot;}&#xA;    out &amp;lt;- []string{&amp;quot;cccccc&amp;quot;, &amp;quot;dddddd&amp;quot;}&#xA;    out &amp;lt;- []string{&amp;quot;e&amp;quot;, &amp;quot;fffff&amp;quot;, &amp;quot;g&amp;quot;}&#xA;    close(out)&#xA;  }()&#xA;  return out&#xA;}&#xA;&#xA;func process(concurrency int, in &amp;lt;-chan []string) &amp;lt;-chan int {&#xA;  var wg sync.WaitGroup&#xA;  wg.Add(concurrency)&#xA;&#xA;  out := make(chan int)&#xA;&#xA;  work := func() {&#xA;    for data := range in {&#xA;      for _, word := range data {&#xA;        out &amp;lt;- len(word)&#xA;      }&#xA;    }&#xA;    wg.Done()&#xA;&#xA;  }&#xA;&#xA;  go func() {&#xA;    for i := 0; i &amp;lt; concurrency; i++ {&#xA;      go work()&#xA;    }&#xA;&#xA;  }()&#xA;&#xA;  go func() {&#xA;    wg.Wait()&#xA;    close(out)&#xA;  }()&#xA;  return out&#xA;}&#xA;&#xA;func store(in &amp;lt;-chan int) &amp;lt;-chan struct{} {&#xA;  done := make(chan struct{})&#xA;  go func() {&#xA;    defer close(done)&#xA;    for data := range in {&#xA;      fmt.Println(data)&#xA;    }&#xA;  }()&#xA;  return done&#xA;}&#xA;&#xA;func main() {&#xA;  // stage 1 ingest data from source&#xA;  in := ingest()&#xA;&#xA;  // stage 2 - process data&#xA;  reduced := process(4, in)&#xA;&#xA;  // stage 3 - store&#xA;  &amp;lt;-store(reduced)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;templating&#34;&gt;Templating&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is a basic program that uses a Struct for its data source:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;  &amp;quot;text/template&amp;quot;&#xA;)&#xA;&#xA;type dataSource struct {&#xA;  Baz int&#xA;}&#xA;&#xA;func (ds dataSource) Foo() string {&#xA;  return &amp;quot;I am foo&amp;quot;&#xA;}&#xA;&#xA;func (ds dataSource) Bar() string {&#xA;  return &amp;quot;I am bar&amp;quot;&#xA;}&#xA;&#xA;const templ = `&#xA;  Foo: {{.Foo}}&#xA;  Piping: {{.Bar | printf &amp;quot;Bar: %s&amp;quot;}}&#xA;  Function: {{.Baz | qux}}&#xA;`&#xA;&#xA;func qux(baz int) int {&#xA;  return baz * 2&#xA;}&#xA;&#xA;// template.Must handles parsing errors better&#xA;var setupTemplate = template.Must(&#xA;  template.New(&amp;quot;whatever&amp;quot;).&#xA;    Funcs(template.FuncMap{&amp;quot;qux&amp;quot;: qux}).&#xA;    Parse(templ),&#xA;)&#xA;&#xA;func main() {&#xA;  ds := dataSource{5}&#xA;&#xA;  if err := setupTemplate.Execute(os.Stdout, ds); err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; is a built-in function for templating and is functionally&#xA;equivalent to &lt;code&gt;fmt.Sprintf&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Program output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Foo: I am foo&#xA;Piping: Bar: I am bar&#xA;Function: 10&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is a HTML templating version:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;html/template&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;var data struct {&#xA;  A string        // untrusted plain text&#xA;  B template.HTML // trusted HTML&#xA;}&#xA;&#xA;const templ = `&amp;lt;p&amp;gt;A: {{.A}}&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;B: {{.B}}&amp;lt;/p&amp;gt;`&#xA;&#xA;func main() {&#xA;  t := template.Must(template.New(&amp;quot;escape&amp;quot;).Parse(templ))&#xA;&#xA;  data.A = &amp;quot;&amp;lt;b&amp;gt;Hello&amp;lt;/b&amp;gt;&amp;quot;&#xA;  data.B = &amp;quot;&amp;lt;b&amp;gt;Hello&amp;lt;/b&amp;gt;&amp;quot;&#xA;&#xA;  if err := t.Execute(os.Stdout, data); err != nil {&#xA;    log.Fatal(err)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;A: &amp;amp;lt;b&amp;amp;gt;Hello&amp;amp;lt;/b&amp;amp;gt;&amp;lt;/p&amp;gt;&#xA;&amp;lt;p&amp;gt;B: &amp;lt;b&amp;gt;Hello&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;error-handling&#34;&gt;Error handling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The following code outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;This is our custom error with some more context prefixed: oh noes!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s the code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;errors&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;)&#xA;&#xA;type errWithContext struct {&#xA;  err error&#xA;  msg string&#xA;}&#xA;&#xA;func (e errWithContext) Error() string {&#xA;  return e.msg + &amp;quot;: &amp;quot; + e.err.Error()&#xA;}&#xA;&#xA;func triggerError() (bool, error) {&#xA;  return false, errors.New(&amp;quot;oh noes!&amp;quot;)&#xA;}&#xA;&#xA;func main() {&#xA;  var e *errWithContext&#xA;&#xA;  _, err := triggerError()&#xA;  if err != nil {&#xA;    e = &amp;amp;errWithContext{&#xA;      err,&#xA;      &amp;quot;This is our custom error with some more context prefixed&amp;quot;,&#xA;    }&#xA;  }&#xA;&#xA;  fmt.Print(e.Error())&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;socket-programming&#34;&gt;Socket Programming&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are two main types of sockets:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;STREAM sockets (e.g. TCP)&lt;/li&gt;&#xA;&lt;li&gt;DATAGRAM sockets (e.g. UDP)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a &amp;ldquo;unix domain socket&amp;rdquo; is actually a physical file&lt;br&gt;&#xA;it&amp;rsquo;s useful for local (same host) data communication&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The principle steps behind a socket is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Create the socket&lt;/li&gt;&#xA;&lt;li&gt;Bind the socket to an address (e.g. &lt;code&gt;127.0.0.1:80&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Listen for socket connections&lt;/li&gt;&#xA;&lt;li&gt;Accept the socket connection&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;There are two main packages in our below example: &lt;code&gt;server.go&lt;/code&gt; and &lt;code&gt;client.go&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Run both of them in separate terminals (e.g. &lt;code&gt;go run ...&lt;/code&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then for the &lt;code&gt;client.go&lt;/code&gt; type your message followed by a new line, for example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Hello World&#xA;Message from server: HELLO WORLD&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Whilst in the &lt;code&gt;server.go&lt;/code&gt; terminal you should see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Starting TCP server...&#xA;Message Received: Hello World&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The code for this program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;server.go&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;bufio&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;strings&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  fmt.Println(&amp;quot;Starting TCP server...&amp;quot;)&#xA;&#xA;  // Listen on all network interfaces (e.g. 0.0.0.0)&#xA;  // Documentation: godoc net Listener | less&#xA;  listener, _ := net.Listen(&amp;quot;tcp&amp;quot;, &amp;quot;:8081&amp;quot;)&#xA;&#xA;  // Accept connection on the port we specified (see above)&#xA;  connection, _ := listener.Accept()&#xA;&#xA;  // Handle incoming connections forever&#xA;  for {&#xA;    // Listen for message to process ending in newline (\n)&#xA;    // Note: single quotes needed for type byte (double quotes is a string)&#xA;    message, _ := bufio.NewReader(connection).ReadString(&#39;\n&#39;)&#xA;&#xA;    // Output message received&#xA;    fmt.Println(&amp;quot;Message Received:&amp;quot;, string(message))&#xA;&#xA;    // Do something with the message (e.g. uppercase it)&#xA;    newmessage := strings.ToUpper(message)&#xA;&#xA;    // Send new string back to client&#xA;    connection.Write([]byte(newmessage + &amp;quot;\n&amp;quot;))&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;client.go&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;bufio&amp;quot;&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  // Open socket connection to a locally runnning TCP server&#xA;  connection, _ := net.Dial(&amp;quot;tcp&amp;quot;, &amp;quot;127.0.0.1:8081&amp;quot;)&#xA;&#xA;  // Handle incoming responses&#xA;  for {&#xA;    // Read the input&#xA;    reader := bufio.NewReader(os.Stdin)&#xA;&#xA;    // Message to be sent&#xA;    // Note: single quotes needed for type byte (double quotes is a string)&#xA;    // Documentation: godoc bufio ReadString | less&#xA;    // ReadString reads until the first occurrence of the delimiter \n in the input&#xA;    text, _ := reader.ReadString(&#39;\n&#39;)&#xA;&#xA;    // Send message to open Socket&#xA;    fmt.Fprintf(connection, text+&amp;quot;\n&amp;quot;)&#xA;&#xA;    // Listen for response&#xA;    // Note: single quotes needed for type byte (double quotes is a string)&#xA;    message, _ := bufio.NewReader(connection).ReadString(&#39;\n&#39;)&#xA;&#xA;    fmt.Println(&amp;quot;Message from server: &amp;quot; + message)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;comparing-maps&#34;&gt;Comparing Maps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This code demonstrates how to be careful about false positives!&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func equal(x, y map[string]int) bool {&#xA;  if len(x) != len(y) {&#xA;    // fail fast&#xA;    return false&#xA;  }&#xA;&#xA;  for k, xv := range x {&#xA;    // Verify &amp;quot;missing&amp;quot; key and &amp;quot;present but zero&amp;quot; key value&#xA;    if yv, ok := y[k]; !ok || yv != xv {&#xA;      return false&#xA;    }&#xA;    &#xA;    /*&#xA;    // The following condition would incorrectly return &amp;quot;true&amp;quot; for the below example comparison!&#xA;    // This is because the empty value for an int type is a zero, while the actual value of x&#39;s key is zero&#xA;    if xv != y[k] {&#xA;      return false&#xA;    }&#xA;    */&#xA;  }&#xA;&#xA;  return true&#xA;}&#xA;&#xA;func main() {&#xA;  fmt.Println(&#xA;    equal(map[string]int{&amp;quot;A&amp;quot;: 0}, map[string]int{&amp;quot;B&amp;quot;: 42}),&#xA;  )&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;zip-file-contents&#34;&gt;Zip File Contents&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;compress/zlib&amp;quot;&#xA;  &amp;quot;io&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  var err error&#xA;&#xA;  // This defends against an error preventing `defer` from being called&#xA;  // As log.Fatal otherwise calls `os.Exit`&#xA;  defer func() {&#xA;    if err != nil {&#xA;      log.Fatalln(&amp;quot;\nDeferred log: \n&amp;quot;, err)&#xA;    }&#xA;  }()&#xA;&#xA;  src, err := os.Create(&amp;quot;source.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;  src.WriteString(&amp;quot;source content&amp;quot;)&#xA;  src.Close()&#xA;&#xA;  dest, err := os.Create(&amp;quot;new.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;&#xA;  openSrc, err := os.Open(&amp;quot;source.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;&#xA;  zdest := zlib.NewWriter(dest)&#xA;  if _, err := io.Copy(zdest, openSrc); err != nil {&#xA;    return&#xA;  }&#xA;&#xA;  // Close these explicitly&#xA;  zdest.Close()&#xA;  dest.Close()&#xA;&#xA;  n, err := os.Open(&amp;quot;new.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;&#xA;  r, err := zlib.NewReader(n)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;  defer r.Close()&#xA;  io.Copy(os.Stdout, r)&#xA;&#xA;  err = os.Remove(&amp;quot;source.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;&#xA;  err = os.Remove(&amp;quot;new.txt&amp;quot;)&#xA;  if err != nil {&#xA;    return&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;shell-commands&#34;&gt;Shell Commands&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is a simple example that writes the output of a command to a file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;os&amp;quot;&#xA;  &amp;quot;os/exec&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  cmd := exec.Command(&amp;quot;ls&amp;quot;)&#xA;&#xA;  outfile, err := os.Create(&amp;quot;./out.txt&amp;quot;)&#xA;  if err != nil {&#xA;    panic(err)&#xA;  }&#xA;  defer outfile.Close()&#xA;&#xA;  cmd.Stdout = outfile&#xA;  cmd.Stderr = outfile&#xA;&#xA;  err = cmd.Start()&#xA;  if err != nil {&#xA;    panic(err)&#xA;  }&#xA;&#xA;  cmd.Wait()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is an older example that printed the results of a command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var (&#xA;  cmdOut []byte&#xA;  err    error&#xA;)&#xA;cmdName := &amp;quot;spurious&amp;quot;&#xA;cmdArgs := []string{&amp;quot;ports&amp;quot;, &amp;quot;--json&amp;quot;}&#xA;if cmdOut, err = exec.Command(cmdName, cmdArgs...).Output(); err != nil {&#xA;  fmt.Fprintln(os.Stderr, &amp;quot;There was an error running &#39;spurious ports --json&#39; command: &amp;quot;, err)&#xA;  os.Exit(1)&#xA;}&#xA;fmt.Println(string(cmdOut))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;new-instance-idiom&#34;&gt;New Instance Idiom&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;type Sqs struct {&#xA;  foo string&#xA;}&#xA;&#xA;func (s *Sqs) create() {&#xA;  fmt.Println(&amp;quot;I&#39;ll create stuff&amp;quot;)&#xA;}&#xA;&#xA;func NewSqs() *Sqs {&#xA;  return &amp;amp;Sqs{&amp;quot;bop&amp;quot;}&#xA;}&#xA;&#xA;func main() {&#xA;  s := NewSqs()&#xA;  fmt.Println(s.foo)&#xA;  s.create()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;json-connection-draining&#34;&gt;JSON Connection Draining&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When using &lt;code&gt;json.NewDecoder&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func main() {&#xA;    http.HandleFunc(&amp;quot;/&amp;quot;, func(w http.ResponseWriter, r *http.Request) {&#xA;        var u User&#xA;        if r.Body == nil {&#xA;            http.Error(w, &amp;quot;Please send a request body&amp;quot;, 400)&#xA;            return&#xA;        }&#xA;        err := json.NewDecoder(r.Body).Decode(&amp;amp;u)&#xA;        if err != nil {&#xA;            http.Error(w, err.Error(), 400)&#xA;            return&#xA;        }&#xA;        fmt.Println(u.Id)&#xA;    })&#xA;    log.Fatal(http.ListenAndServe(&amp;quot;:8080&amp;quot;, nil))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;it doesn&amp;rsquo;t read the response Body completely. So when closing the response&#xA;you might get an error as a stray &lt;code&gt;\n&lt;/code&gt; could be present later on. You&amp;rsquo;ll need to&#xA;drain the response instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;defer func() {&#xA;  io.CopyN(ioutil.Discard, r.Body, 512)&#xA;  r.Body.Close()&#xA;}()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/google/go-github/pull/317&#34; target=&#34;_blank&#34;&gt;https://github.com/google/go-github/pull/317&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;writing-your-own-marshal-unmarshal-functions&#34;&gt;Writing your own Marshal/Unmarshal functions&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;bytes&amp;quot;&#xA;    &amp;quot;encoding/json&amp;quot;&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;strconv&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    a := make(Stuff)&#xA;    a[1] = &amp;quot;asdf&amp;quot;&#xA;    a[-1] = &amp;quot;qwer&amp;quot;&#xA;    fmt.Println(&amp;quot;Initial:     &amp;quot;, a)&#xA;&#xA;    stuff, _ := json.Marshal(a)&#xA;    fmt.Println(&amp;quot;Serialized:  &amp;quot;, string(stuff))&#xA;&#xA;    b := make(Stuff)&#xA;    _ = json.Unmarshal(stuff, &amp;amp;b)&#xA;    fmt.Println(&amp;quot;Deserialized:&amp;quot;, b)&#xA;}&#xA;&#xA;type Stuff map[int]string&#xA;&#xA;// MarshalJSON works the same as the underlying json.Marshal would&#xA;func (this Stuff) MarshalJSON() ([]byte, error) {&#xA;    buffer := bytes.NewBufferString(&amp;quot;{&amp;quot;)&#xA;    length := len(this)&#xA;    count := 0&#xA;    for key, value := range this {&#xA;        jsonValue, err := json.Marshal(value)&#xA;        if err != nil {&#xA;            return nil, err&#xA;        }&#xA;        buffer.WriteString(fmt.Sprintf(&amp;quot;\&amp;quot;%d\&amp;quot;:%s&amp;quot;, key, string(jsonValue)))&#xA;        count++&#xA;        if count &amp;lt; length {&#xA;            buffer.WriteString(&amp;quot;,&amp;quot;)&#xA;        }&#xA;    }&#xA;    buffer.WriteString(&amp;quot;}&amp;quot;)&#xA;    return buffer.Bytes(), nil&#xA;&#xA;  // for example you could totally change the behaviour...&#xA;  /*&#xA;    buffer := bytes.NewBufferString(&amp;quot;{&amp;quot;)&#xA;    buffer.WriteString(&amp;quot;}&amp;quot;)&#xA;    return buffer.Bytes(), nil&#xA;    */&#xA;}&#xA;&#xA;// UnmarshalJSON works the same as the underlying json.Unmarshal would&#xA;func (this Stuff) UnmarshalJSON(b []byte) error {&#xA;    var stuff map[string]string&#xA;    err := json.Unmarshal(b, &amp;amp;stuff)&#xA;    if err != nil {&#xA;        return err&#xA;    }&#xA;    for key, value := range stuff {&#xA;        numericKey, err := strconv.Atoi(key)&#xA;        if err != nil {&#xA;            return err&#xA;        }&#xA;        this[numericKey] = value&#xA;    }&#xA;    return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This means you can also leverage custom type checking:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See: &lt;a href=&#34;http://blog.tamizhvendan.in/blog/2017/06/24/leveraging-interfaces-in-golang-part-1/&#34; target=&#34;_blank&#34;&gt;leveraging interfaces in&#xA;golang&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-hitchhikers-guide/</guid>
      <link>https://www.integralist.co.uk/posts/go-hitchhikers-guide/</link>
      <pubDate>Fri, 02 Dec 2016 00:00:00 +0000</pubDate>
      <title>Hitchhikers Guide to Go</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I decided recently to read a book on the C programming language. The idea was to learn some more low-level concepts that other higher-level languages were abstracting away from me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This write up is the result of some of those learnings. This is not a &amp;ldquo;how do you write C code&amp;rdquo;. This is a grouping of topics and concepts that I found interesting and thought might be useful to other developers with similar interests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some of the stuff covered will be obvious, but I appreciate some concepts won&amp;rsquo;t be obvious for all readers, so this write up will end up crossing back and forth between different &amp;lsquo;levels&amp;rsquo; of understanding and experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In other words: your mileage may vary&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;compilation&#34;&gt;Compilation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When writing a program in a language like &lt;a href=&#34;https://en.wikipedia.org/wiki/C_(programming_language)&#34; target=&#34;_blank&#34;&gt;C&lt;/a&gt;, you&amp;rsquo;ll find that by itself it is not executable (i.e. you can&amp;rsquo;t run a C file directly). You need to convert the C source code into &lt;a href=&#34;https://en.wikipedia.org/wiki/Machine_code&#34; target=&#34;_blank&#34;&gt;machine code&lt;/a&gt; (i.e. something the computer&amp;rsquo;s CPU can understand).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Machine code is as low-level as you can get when interacting with a computer. So the C language is considered a &amp;lsquo;higher-level&amp;rsquo; abstraction to save us from having to write machine code ourselves.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A language like &lt;a href=&#34;https://www.python.org/&#34; target=&#34;_blank&#34;&gt;Python&lt;/a&gt; is an even &amp;lsquo;higher-level&amp;rsquo; abstraction, to save us from having to write C&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the Python language is actually written in C&lt;br&gt;&#xA;Although there are other Python interpreters implemented in different languages&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In order to convert C code into machine code, we need a compiler.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Strictly speaking you also need a &lt;a href=&#34;https://en.wikipedia.org/wiki/Linker_(computing)&#34; target=&#34;_blank&#34;&gt;linker&lt;/a&gt; which takes multiple compiled objects and places them into a single executable file. Generally speaking, when we say &amp;ldquo;compile a C file&amp;rdquo;, we&amp;rsquo;re really combining two separate steps (compiling and linking) into the single generic term &amp;ldquo;compile&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;compilers&#34;&gt;Compilers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To compile C source code into an executable you need a compiler, of which there are many options. The two most popular being LLVM&amp;rsquo;s &lt;code&gt;clang&lt;/code&gt; and GNU&amp;rsquo;s &lt;code&gt;gcc&lt;/code&gt;. You might also find on your computer a &lt;code&gt;cc&lt;/code&gt; command, but typically this is aliased to an existing compiler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Mac OS doesn&amp;rsquo;t provide a compiler by default. But if you install X-Code you&amp;rsquo;ll get the LLVM&amp;rsquo;s suite of compilers. Below we see that we get quite a few alias&amp;rsquo; and all of them point to the same embeded LLVM compiler:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gcc --version&#xA;Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1&#xA;Apple LLVM version 8.0.0 (clang-800.0.38)&#xA;Target: x86_64-apple-darwin15.6.0&#xA;Thread model: posix&#xA;InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin&#xA;                                                                   &#xA;$ llvm-gcc --version&#xA;Apple LLVM version 8.0.0 (clang-800.0.38)&#xA;Target: x86_64-apple-darwin15.6.0&#xA;Thread model: posix&#xA;InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin&#xA;                                                                   &#xA;$ clang --version&#xA;Apple LLVM version 8.0.0 (clang-800.0.38)&#xA;Target: x86_64-apple-darwin15.6.0&#xA;Thread model: posix&#xA;InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin&#xA;                                                                   &#xA;$ cc --version&#xA;Apple LLVM version 8.0.0 (clang-800.0.38)&#xA;Target: x86_64-apple-darwin15.6.0&#xA;Thread model: posix&#xA;InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first two alias&amp;rsquo; &lt;code&gt;gcc&lt;/code&gt; and &lt;code&gt;llvm-gcc&lt;/code&gt; are a little bit confusing and also a bit misleading, as they&amp;rsquo;re not GNU&amp;rsquo;s version. They&amp;rsquo;re still the LLVM&amp;rsquo;s compiler but with some modifications. In the first instance (&lt;code&gt;gcc&lt;/code&gt;) the compiler is configured to use some additional libraries that are provided by c++.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You can tell this by the flag &lt;code&gt;--with-gxx-include-dir&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth noting that with a standard/simple C source code file, all these alias&amp;rsquo; work to compile the source code into an executable. But some compilers allow you to utilise additional extensions not provided by the standard C language (so you need to be careful your code doesn&amp;rsquo;t try to utilise something that&amp;rsquo;s not available at compilation time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;LLVM&amp;rsquo;s licensing is BSD, meaning Apple can embed it within their own software that is not GPL-licensed. Typically LLVM&amp;rsquo;s compiler is faster than GNU&amp;rsquo;s, but in some cases it might not support all the same targets as GNU&amp;rsquo;s.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For more comparison details see &lt;a href=&#34;http://clang.llvm.org/comparison.html&#34; target=&#34;_blank&#34;&gt;http://clang.llvm.org/comparison.html&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;c11-safe-functions&#34;&gt;C11 safe functions?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll likely be told that some functions provided within C aren&amp;rsquo;t safe (usually around string manipulation). For example, some string functions allow for overflow of data because they don&amp;rsquo;t check that the underlying array data structure is able to contain the strings being manipulated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;C11 compatible compilers will provide an additional set of string functions that are &lt;em&gt;considered&lt;/em&gt; safe (although this is a contentious area of discussion as some C programmers believe that these functions are just as unsafe and if anything the claims are misleading! &lt;a href=&#34;http://stackoverflow.com/questions/40829032/how-to-install-c11-compiler-on-mac-os-with-optional-string-functions-included/40839702#40839702&#34; target=&#34;_blank&#34;&gt;See this comment on Stack Overflow which goes into more detail&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve also discovered that none of the compilers I have on my OS support these functions, and I&amp;rsquo;ve since discovered one of the few environments to support these functions is the Windows platform&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Below is an example C file that demonstrates how to check if your compiler supports these additional safe functions:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void)&#xA;{&#xA;  #if defined __STDC_LIB_EXT1__&#xA;    printf(&amp;quot;Optional functions are defined.\n&amp;quot;);&#xA;  #else&#xA;    printf(&amp;quot;Optional functions are not defined.\n&amp;quot;);&#xA;  #endif&#xA;  &#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If your compiler supports these optional (safe) string functions, then to &lt;em&gt;enable&lt;/em&gt; them you&amp;rsquo;ll need to add a &lt;code&gt;define&lt;/code&gt; directive that modifies the subsequent header file. But you also need to add this directive &lt;em&gt;before&lt;/em&gt; you include the preprocessor directive that imports the &lt;code&gt;string.h&lt;/code&gt; header:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#define __STDC_WANT_LIB_EXT1__ 1&#xA;#include &amp;lt;string.h&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t set &lt;code&gt;__STDC_WANT_LIB_EXT1__&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;, then the header &lt;code&gt;string.h&lt;/code&gt; will utilise the old (unsafe) string functions.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;hello-world&#34;&gt;Hello World&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is a simple &amp;lsquo;hello world&amp;rsquo; C example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;   // pre-processor directive to include code file at compile time&#xA;#define NAME &amp;quot;World&amp;quot; // pre-processor directive to substitute any reference to NAME _before_ compilation&#xA;&#xA;// returns an int type and takes in no arguments (void)&#xA;int main(void) {&#xA;  printf(&amp;quot;hello %s&amp;quot;, NAME); &#xA;  return 0;          // zero indicates no problems (i.e. EXIT CODE)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to note that the directives &lt;code&gt;#include&lt;/code&gt; and &lt;code&gt;#define&lt;/code&gt; are &amp;lsquo;processed&amp;rsquo; at the start of the compilation process. This is at the request of the compiler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So it&amp;rsquo;ll be one of the compiler&amp;rsquo;s first steps to pull in the preprocessor and have it ensure the file is setup ready for the rest of the compilation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You would compile this file like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cc hello-world.c -o hw&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now you have a macOS compatible executable:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;./hw # prints the message &amp;quot;Hello World&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;To cross-compile for another OS (e.g. Linux) then use Docker or a VM&lt;br&gt;&#xA;Other modern languages like &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; or &lt;a href=&#34;https://www.rust-lang.org/&#34; target=&#34;_blank&#34;&gt;Rust&lt;/a&gt; allow you to cross-compiler without a VM&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;constants-vs-directives&#34;&gt;Constants vs Directives&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We saw in the above &amp;lsquo;Hello World&amp;rsquo; example the use of the directive &lt;code&gt;#define&lt;/code&gt; which allowed us to use a single identifier (&lt;code&gt;NAME&lt;/code&gt; in this case) throughout our program. The benefit is that we can change the value once and have it updated everywhere.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But do not get this confused with a variable. It is not. This is just a sequence of characters that are blindly replaced at the pre-processing stage. The value assigned to &lt;code&gt;NAME&lt;/code&gt; will be replaced inside your program regardless of whether it&amp;rsquo;s valid code or not. Meaning it could cause an ambiguous compiler error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the other hand you can define a proper constant like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void) {&#xA;  const char NAME[] = &amp;quot;World&amp;quot;;&#xA;  printf(&amp;quot;Hello %s&amp;quot;, NAME);&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this gives you is a variable that has an actual type assigned to it (&lt;code&gt;char&lt;/code&gt;). Meaning the compiler will help you identify an incorrect value if necessary, much more easily than using the &lt;code&gt;#define&lt;/code&gt; directive.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quotations&#34;&gt;Quotations&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In C single quotes denote a &lt;code&gt;char&lt;/code&gt; type and double quotes denote a string.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you had the following code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char foo = &#39;a&#39;;&#xA;printf(&amp;quot;foo: %s\n&amp;quot;, foo);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It would error with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;format specifies type &#39;char *&#39; but the argument has type &#39;char&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To get it to work you need to provide the memory address location of &lt;code&gt;foo&lt;/code&gt; using the address-of operator (&lt;code&gt;&amp;amp;&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char foo = &#39;a&#39;;&#xA;printf(&amp;quot;foo: %s\n&amp;quot;, &amp;amp;foo);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll come back to the &lt;code&gt;&amp;amp;&lt;/code&gt; operator (and understand what &lt;code&gt;*&lt;/code&gt; means) later, when we discuss &lt;a href=&#34;#8&#34;&gt;pointers&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;char-type&#34;&gt;Char Type&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When creating a variable, and assigning a string to it, the value assigned is really a pointer to a location in memory. The &lt;code&gt;char&lt;/code&gt; type is used when storing characters such as &lt;code&gt;&#39;a&#39;&lt;/code&gt;, but it also allows storing of strings such as &lt;code&gt;&amp;quot;abc&amp;quot;&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When assigning a string, the pointer is to an &lt;em&gt;array&lt;/em&gt; where each element of the array is a character of the provided string. For example the string &lt;code&gt;&amp;quot;abc&amp;quot;&lt;/code&gt; would be stored in an array that looked something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see section &amp;lsquo;&lt;a href=&#34;#7&#34;&gt;Null Terminator&lt;/a&gt;&amp;rsquo; to clarify above code&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This happens even if the string you provide is just one character. Although, depending on your program&amp;rsquo;s design, it could be argued that you should not have assigned a single character string, but instead used single quotes to represent a single &lt;code&gt;char&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When assigning a character (e.g. &lt;code&gt;a&lt;/code&gt;) to a variable of type &lt;code&gt;char&lt;/code&gt; it takes on dual duty. Meaning the char type variable can represent the specific character &lt;code&gt;a&lt;/code&gt; but really it stores the ASCII integer code that defines that character.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Take a look at an &lt;a href=&#34;http://www.asciitable.com/&#34; target=&#34;_blank&#34;&gt;ASCII table&lt;/a&gt; to identify the code associated with a particular character&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This means we could also directly assign the integer &lt;code&gt;97&lt;/code&gt; instead of the character &lt;code&gt;a&lt;/code&gt; to the char type variable. But also, and more interestingly, because of these characteristics we can perform arithmetic on the variable:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void) {&#xA;  // print character and its associated ascii code integer&#xA;  char foo = &#39;a&#39;;&#xA;  printf(&amp;quot;foo: %c (%d)\n&amp;quot;, foo, foo); // a (97)&#xA;&#xA;  // now modify the variable by adding to it&#xA;  foo = foo + 2;&#xA;&#xA;  // we can see the character/integer reflects the change&#xA;  printf(&amp;quot;foo: %c (%d)\n&amp;quot;, foo, foo); // c (99)&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;null-terminator&#34;&gt;Null Terminator&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider the following code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char my_string[4] = &amp;quot;abc&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason we specify a length of 4 and not 3 (as you would expect with a string that is three characters in length), is because the underlying array that &lt;code&gt;my_string&lt;/code&gt; is being pointed towards looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;\0&amp;quot;] // yes it does actually have four elements&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The last element is known as the &lt;a href=&#34;https://en.wikipedia.org/wiki/Null-terminated_string&#34; target=&#34;_blank&#34;&gt;null terminator&lt;/a&gt;. When this data is stored in memory, we can start at the location in memory (the &lt;em&gt;address&lt;/em&gt;) where the first element is stored and then step through memory until we reach the null terminator; where we&amp;rsquo;ll then find the end of the string.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can set your variable to be the actual length of the content (e.g. &lt;code&gt;char my_string[1] = &amp;quot;a&amp;quot;;&lt;/code&gt;) but in some instances this can cause strange overlaps of data and strictly speaking isn&amp;rsquo;t valid code either&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;pointers&#34;&gt;Pointers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When declaring a variable, the computer sets aside some memory for the variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, the variable name is linked to the location in memory that was set aside for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, the value you want to assign to the variable is placed into the relevant location of memory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s consider the following code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void) {&#xA;  int foo = 1;&#xA;  printf(&amp;quot;foo: %d\n&amp;quot;, foo);&#xA;&#xA;  int *bar;&#xA;  int bar_val = 1;&#xA;  printf(&amp;quot;bar_val: %d\n&amp;quot;, bar_val);&#xA;  bar = &amp;amp;bar_val;&#xA;  printf(&amp;quot;bar: %p\n&amp;quot;, bar);&#xA;  int bar_get_val = *bar;&#xA;  printf(&amp;quot;bar_get_val: %d\n&amp;quot;, bar_get_val);&#xA;&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we see that we create a &lt;code&gt;foo&lt;/code&gt; variable and assign &lt;code&gt;1&lt;/code&gt; to it. We then print that integer in the typical way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next, we make a slightly more convoluted version, but this time we&amp;rsquo;re utilising a pointer in order to help us understand what they are and how to use them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are each of the steps broken down:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;int *bar;&lt;/code&gt;: we declare a pointer variable † called &lt;code&gt;bar&lt;/code&gt; of type &lt;code&gt;int&lt;/code&gt; but we don&amp;rsquo;t initialize it with a value&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;int bar_val = 1;&lt;/code&gt;: we both declare &lt;em&gt;and&lt;/em&gt; initialize the variable &lt;code&gt;bar_val&lt;/code&gt; as type &lt;code&gt;int&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;bar = &amp;amp;bar_val;&lt;/code&gt;: we initialize the pointer variable &lt;code&gt;bar&lt;/code&gt; with the memory address of &lt;code&gt;bar_val&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;int bar_get_val = *bar;&lt;/code&gt;: we dereference the address (i.e. follow the pointer) assigned to &lt;code&gt;bar&lt;/code&gt; which leads us to the &lt;em&gt;value&lt;/em&gt; stored in that memory slot&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† meaning we will be assigning an address to this pointer&lt;br&gt;&#xA;and the content at that memory address location will also be of type &lt;code&gt;int&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The output of this program is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo: 1&#xA;bar_val: 1&#xA;bar: 0x7fff59a1769c&#xA;bar_get_val: 1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, so there are some things that we need to clarify and that&amp;rsquo;s the &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;&amp;amp;&lt;/code&gt; operators.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;*&lt;/code&gt;: value-at-address operator (used when declaring a pointer &lt;em&gt;and&lt;/em&gt; when dereferencing a pointer)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;: address-of operator (used to reference the memory address of a variable)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The first thing we should be aware of is that we&amp;rsquo;re not able to print a declared variable that has no value initialized for it. So imagine the following code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;int *bar;&#xA;printf(&amp;quot;bar: %d\n&amp;quot;, bar);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would cause the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;format specifies type &#39;int&#39; but the argument has type &#39;int *&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which makes sense, as we&amp;rsquo;ve declared the variable as the type &lt;code&gt;*bar&lt;/code&gt;. So we can start by fixing that issue and correctly specifying the second argument to &lt;code&gt;printf&lt;/code&gt; as &lt;code&gt;*bar&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;int *bar;&#xA;printf(&amp;quot;bar: %d\n&amp;quot;, *bar);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;printf&lt;/code&gt; will now try to use &lt;code&gt;*&lt;/code&gt; to dereference the value from the variable &lt;code&gt;bar&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Unfortunately this code still causes an error. This time:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;variable &#39;bar&#39; is uninitialized when used here&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which again makes sense. Nothing more to say about that portion of the code, I just wanted to make it clear what happens when you try to print an uninitialized variable (and also what happens when that variable is a pointer type).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So continuing through the program, the next line of interest is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bar = &amp;amp;bar_val;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This gives us the actual location in memory for the variable &lt;code&gt;bar_val&lt;/code&gt; (i.e. &lt;code&gt;0x7fff59a1769c&lt;/code&gt;). So the value assigned to &lt;code&gt;bar&lt;/code&gt; isn&amp;rsquo;t &lt;code&gt;1&lt;/code&gt;, but the address of &lt;code&gt;1&lt;/code&gt; in memory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, we declare and initialize the variable &lt;code&gt;bar_get_val&lt;/code&gt; with the actual value of &lt;code&gt;1&lt;/code&gt;, and we do that by using &lt;code&gt;*&lt;/code&gt; to deference the variable &lt;code&gt;bar&lt;/code&gt; which contains a memory address:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;int bar_get_val = *bar;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What that means, is &lt;code&gt;bar&lt;/code&gt; holds a &lt;em&gt;memory address&lt;/em&gt;, which isn&amp;rsquo;t a concrete value, it&amp;rsquo;s an indirection to somewhere else. Hence we would say &lt;code&gt;bar&lt;/code&gt; &lt;em&gt;points&lt;/em&gt; to the actual value&amp;rsquo;s location and explains why we use the &amp;lsquo;value-at-address&amp;rsquo; operator &lt;code&gt;*&lt;/code&gt; to deference the value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code shows how to print the location in memory of a variable even if it wasn&amp;rsquo;t declared as a pointer, simply by using the address-at operator &lt;code&gt;&amp;amp;&lt;/code&gt; which itself indicates a pointer to another location:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char foo = &#39;a&#39;;&#xA;printf(&amp;quot;address of foo: %p\n&amp;quot;, &amp;amp;foo);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;&amp;amp;&lt;/code&gt; isn&amp;rsquo;t tied to &lt;code&gt;*&lt;/code&gt; in any way.&lt;br&gt;&#xA;Its purpose is just to return the memory address for a given variable&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Remember, a memory address isn&amp;rsquo;t the value itself but a reference to where the value can be found. One analogy I&amp;rsquo;ve seen is of your home address on an envelope: the envelope isn&amp;rsquo;t your home, nor is the address written on the envelope. The envelope just indicates where your home can be found.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One last thing to consider/remember is that C doesn&amp;rsquo;t have a String type. It stores strings in an array data structure. An array will automatically return the address location of its first element to the variable it is assigned to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why you may have seen a &lt;code&gt;char&lt;/code&gt; pointer being assigned a variable &lt;em&gt;without&lt;/em&gt; the need to use the &lt;code&gt;&amp;amp;&lt;/code&gt; operator to get the memory address of that variable (because the variable, in this case an array, already provides a memory address).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example shows this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char message[6] = &amp;quot;hello&amp;quot;; // array data structure used and memory location for message[0] returned&#xA;char *messagePtr = message; // no need to use &amp;amp;message now&#xA;printf(&amp;quot;my pointer: %p\n&amp;quot;, messagePtr);&#xA;printf(&amp;quot;my message: %s\n&amp;quot;, message);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;compare C pointers and Go pointers here &lt;a href=&#34;https://dave.cheney.net/2014/03/17/pointers-in-go&#34; target=&#34;_blank&#34;&gt;https://dave.cheney.net/2014/03/17/pointers-in-go&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In C there are two ways to define a pointer:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;char* foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;char *foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Both of which are equivalent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although the first seems like the clearer option (as someone new to C would read it: &amp;ldquo;define a variable called &lt;code&gt;foo&lt;/code&gt; of type &amp;lsquo;character pointer&amp;rsquo;&amp;rdquo;) compared to the second option (which could lead them to think the variable name was &lt;code&gt;*foo&lt;/code&gt; not &lt;code&gt;foo&lt;/code&gt;). For me the second option is preferred because otherwise the following code becomes a bit ambiguious:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char* foo, bar;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You might (incorrectly) think this would create two variables, both of type &amp;lsquo;character pointer&amp;rsquo;, but really only &lt;code&gt;foo&lt;/code&gt; is the pointer and &lt;code&gt;bar&lt;/code&gt; is a normal &lt;code&gt;char&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whereas using the second format (&lt;code&gt;char *foo&lt;/code&gt;), this code becomes much clearer:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char *foo, bar;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Lastly, if you want to create a &lt;code&gt;const&lt;/code&gt; that happens to be a pointer, then the syntax is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;int count = 43;&#xA;int *const pcount = &amp;amp;count;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We prefix the &lt;code&gt;const&lt;/code&gt; keyword with the value-at operator &lt;code&gt;*&lt;/code&gt; and not the variable name.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;arrays&#34;&gt;Arrays&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider the following code (which is broken by the way):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void) {&#xA;  char my_string = &amp;quot;abc&amp;quot;;&#xA;  printf(&amp;quot;my_string: %s&amp;quot;, my_string);&#xA;&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This code has the following compiler error:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;incompatible pointer to integer conversion initializing &#39;char&#39; with an expression of type &#39;char [4]&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this error tells us is that the variable &lt;code&gt;my_string&lt;/code&gt; has a type of &lt;code&gt;char [4]&lt;/code&gt;, meaning it is actually an array (hence the &lt;code&gt;[4]&lt;/code&gt; syntax) and so we should have declared the variable like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char my_string[4] = &amp;quot;abc&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We saw earlier why this is required, when talking about &lt;a href=&#34;#7&#34;&gt;null terminators&lt;/a&gt;. But just to recap, it&amp;rsquo;s because a string should be stored within an array data structure. So we need to declare it as such.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also learned earlier (using the above example) why the length of the array is 4 and not 3 (which you may initially have expected which a string of three characters), again to recap: this is because of the extra element added to the array for you &amp;ldquo;\0&amp;rdquo; (the null terminator).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, the reason I&amp;rsquo;m talking about arrays is because in the original code above (the one before declaring the variable correctly) there were actually two errors linked together. The second part of the error was:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;format specifies type &#39;char *&#39; but the argument has type &#39;char&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this error tells us is that &lt;code&gt;printf&lt;/code&gt; was expecting a pointer but all it got was something of a &lt;code&gt;char&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When declaring the variable as an array, we fix both errors.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But both these errors has led some people to incorrectly assume that an array is a pointer, when it is not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s recap why this works.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When assigning a string, the compiler expects the contents to be stored within an array. Each element within the array is an address to the value given to it in memory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in our example above (i.e. the string &lt;code&gt;&amp;quot;abc&amp;quot;&lt;/code&gt;), &lt;code&gt;&amp;quot;a&amp;quot;&lt;/code&gt; is stored in memory and the address of that memory is placed in &lt;code&gt;my_string[0]&lt;/code&gt;. Next &lt;code&gt;&amp;quot;b&amp;quot;&lt;/code&gt; is stored in memory and the address of that memory is placed in &lt;code&gt;my_string[1]&lt;/code&gt; and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A pointer in contrast is a single location in memory, whereas an array hold lots of memory addresses.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because of this, an array variable automatically points to the first element within the array.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why if you try to &lt;code&gt;printf&lt;/code&gt; a string, the compiler will complain if you don&amp;rsquo;t provide a pointer. Because it expects a string to have been stored within an array (which our earlier example didn&amp;rsquo;t). But when storing a string inside an array, the variable that is passed to &lt;code&gt;printf&lt;/code&gt; would &lt;em&gt;already&lt;/em&gt; be a pointer, due to it automatically referencing the first array element as its value.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Interestingly, an array&amp;rsquo;s type is made up of the element type + the overall array dimension. So &lt;code&gt;int foo[3]&lt;/code&gt; is a different type to &lt;code&gt;int bar[4]&lt;/code&gt;. Even though the value type &lt;code&gt;int&lt;/code&gt; is the same, the array dimension (size/length) is different.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you want to know how many bytes an array will occupy, then you calculate it based upon the number of elements multiplied by the size of each element.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, you can define and initialize a string &lt;em&gt;without&lt;/em&gt; specifying an array dimension (i.e. no size):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char foobar[] = &amp;quot;No dimension provided!&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this does is leave the decision of how much memory to allocate to the compiler. But you can only do this when you initialize the variable with a value. Although you couldn&amp;rsquo;t do &lt;code&gt;char foobar[];&lt;/code&gt; as there is no value for the compiler to utilise to know how much memory to allocate.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;enumerators&#34;&gt;Enumerators&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Enumerators allow you to define new variable types. They automatically assign numerical values to each of the identifiers within the enumerator (although you do also have control over the specific values as well).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This concept is best explained by way of example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;&#xA;&#xA;int main(void) {&#xA;  enum weekend {Saturday, Sunday};     // 0, 1&#xA;  enum weekend today = Sunday;         // 1&#xA;  enum weekend saturday = Saturday;    // 0&#xA;  enum weekend yesterday = today - 1;  // 0 now yesterday is Saturday&#xA;  printf(&amp;quot;today %d\n&amp;quot;, today);&#xA;  printf(&amp;quot;saturday %d\n&amp;quot;, saturday);&#xA;  printf(&amp;quot;yesterday %d\n&amp;quot;, yesterday);&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see that we define a &lt;code&gt;weekend&lt;/code&gt; type and each element in that set is assigned an automatic numerical value (&lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we create a new variable &lt;code&gt;today&lt;/code&gt; of type &lt;code&gt;weekend&lt;/code&gt; and assign it the value &lt;code&gt;Sunday&lt;/code&gt;, which means it is effectively assigned the value &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also notice this is why we&amp;rsquo;re able to do simple arithmetic with the &lt;code&gt;today&lt;/code&gt; variable (e.g. &lt;code&gt;today - 1&lt;/code&gt; to get &lt;code&gt;0&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you wish to provide your own values you can:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;enum bool {&#xA;  true = 1,&#xA;  false = 2&#xA;};&#xA;&#xA;enum bool on = true;&#xA;enum bool off = false;&#xA;&#xA;printf(&amp;quot;on: %d\n&amp;quot;, on);   // 1&#xA;printf(&amp;quot;off: %d\n&amp;quot;, off); // 2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;memory-allocation-with-different-types&#34;&gt;Memory Allocation with different Types&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Read &lt;a href=&#34;/posts/bits-and-bytes/&#34;&gt;this article&lt;/a&gt; if you need a refresher on understanding RAM, bits, binary and stuff like that&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;array&#34;&gt;Array&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Consider the following code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;int foo[3] = {1,2,3};&#xA;printf(&amp;quot;foo variable points to = %p\n&amp;quot;, foo);&#xA;&#xA;int i = 0;&#xA;do {&#xA;  printf(&amp;quot;foo[%u] = %p\n&amp;quot;, i, (void *)(&amp;amp;foo[i]));&#xA;  i++;&#xA;} while(i &amp;lt; 3);&#xA;&#xA;printf(&amp;quot;sizeof(foo) = %lu\n&amp;quot;, sizeof(foo));&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So in this piece of code we create an array and assign it to &lt;code&gt;foo&lt;/code&gt; (where the first element&amp;rsquo;s memory address will ultimately be referenced).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we print out what the &lt;code&gt;foo&lt;/code&gt; variable points to, which for me outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo variable points to = 0x7fff525fd6ac&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then we loop over the &lt;code&gt;foo&lt;/code&gt; array and print out each element&amp;rsquo;s address, which for me outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo[0] = 0x7fff525fd6ac&#xA;foo[1] = 0x7fff525fd6b0&#xA;foo[2] = 0x7fff525fd6b4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that the &lt;code&gt;foo&lt;/code&gt; variable and the first element of the &lt;code&gt;foo&lt;/code&gt; array are the same value: &lt;code&gt;0x7fff525fd6ac&lt;/code&gt;, which is the address of the memory location for the value &lt;code&gt;1&lt;/code&gt; assigned to &lt;code&gt;foo[0]&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So this demonstrates clearly that when a variable is assigned an array, then it will actually point to the memory address of that array&amp;rsquo;s first element.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we look at &lt;code&gt;(void *)(&amp;amp;foo[i])&lt;/code&gt;, shown in the above example code, we find this interesting setup where by we&amp;rsquo;re casting the address to &lt;code&gt;void&lt;/code&gt;. Well you don&amp;rsquo;t need to do that unless you&amp;rsquo;re passing a variable that is itself a pointer variable to another variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;code&gt;int foo = 1; int *pFoo = foo&lt;/code&gt;. Here you would cast to &lt;code&gt;void&lt;/code&gt; to prevent a possible warning from the compiler when using &lt;code&gt;%p&lt;/code&gt; within a &lt;code&gt;printf&lt;/code&gt; statement.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is because &lt;code&gt;printf&lt;/code&gt; and &lt;code&gt;%p&lt;/code&gt; will expect the value to be a pointer type, but in cases where you have a pointer variable assigned an &lt;code&gt;int&lt;/code&gt; variable, then the type of &lt;code&gt;&amp;amp;pFoo&lt;/code&gt; would actually be a &amp;lsquo;pointer to pointer to int&amp;rsquo;. It just highlights the importance of paying attention to the variables you&amp;rsquo;re defining and what they&amp;rsquo;re pointing to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally we print the size of the &lt;code&gt;foo&lt;/code&gt; variable, which outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sizeof(foo) = 12&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You might wonder  where the value &lt;code&gt;12&lt;/code&gt; comes from? Well, this goes back to how data is stored in memory (i.e. a block of memory is 1 byte; so 8 bits). We defined the type of the array to be &lt;code&gt;int&lt;/code&gt; and (depending on the compiler) that will be either two bytes, four bytes or eight bytes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For most 32 bit systems the size of &lt;code&gt;int&lt;/code&gt; would be four bytes. You can always use &lt;code&gt;sizeof(int)&lt;/code&gt; to check:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;printf(&amp;quot;sizeof(int): %ld\n&amp;quot;, sizeof(int)); // 4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So looking back at our example, we have three array elements, and if each element takes up four bytes then it makes sense the size of the array would be &lt;code&gt;12&lt;/code&gt; (i.e. &lt;code&gt;4 + 4 + 4 = 12&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To calculate the number of items within the array itself, rather than the number of bytes, you can use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;size_t element_count = sizeof foo/sizeof foo[0];&#xA;printf(&amp;quot;element_count: %zu\n&amp;quot;, element_count); // 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;%z&lt;/code&gt; is for &lt;code&gt;size_t&lt;/code&gt; and the &lt;code&gt;u&lt;/code&gt; prevents an &lt;code&gt;invalid conversion specifier&lt;/code&gt; error.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;signed-vs-unsigned&#34;&gt;Signed vs Unsigned&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In C you can define an integer to be either &lt;code&gt;signed&lt;/code&gt; or &lt;code&gt;unsigned&lt;/code&gt;. The former means the number can be both negative and positive as well as zero. Whereas the latter is always positive.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;typically, if a number is negative, you&amp;rsquo;ll prefix it with &lt;code&gt;-&lt;/code&gt;. If the number is positive, then it is just the number. For example, &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;. This is a little more convoluted in binary though (resulting in concepts such as &amp;lsquo;ones complement&amp;rsquo; and &amp;lsquo;twos complement&amp;rsquo; - Google it if you want to know more though).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t need to explicitly provide the &lt;code&gt;signed&lt;/code&gt; keyword (e.g. &lt;code&gt;signed int &amp;lt;var_name&amp;gt;&lt;/code&gt;), it&amp;rsquo;s just implied.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The latter (&lt;code&gt;unsigned&lt;/code&gt;) is an integer that can only be positive. So if you need to store an integer and you know the value will always be zero or positive, then you can define it as being unsigned and the compiler can make appropriate optimisations based on that understanding.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So although the underlying memory allocation is the same for signed or unsigned, the actual values represented are slightly different, in that unsigned allows for storing values that are twice the size of signed, because half of signed&amp;rsquo;s values have to account for negatives.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;reallocating-memory&#34;&gt;Reallocating Memory&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With strings you typically define them as follows (i.e. the underlying data structure is an array):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char names[20] = &amp;quot;hello&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But this can result in wasted reserved memory. Also, when reading input from stdin (e.g. user input) the amount of characters entered could exceed the specified reserved memory allocation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example, given as a &lt;a href=&#34;http://stackoverflow.com/questions/8164000/how-to-dynamically-allocate-memory-space-for-a-string-and-get-that-string-from-u&#34; target=&#34;_blank&#34;&gt;Stack Overflow&lt;/a&gt; response, that reads each character from stdin and reallocates the memory space if required (it&amp;rsquo;s advised that you ensure reallocation of memory is done as a multiple; such as double the size):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char *getln()&#xA;{&#xA;    char *line = NULL, *tmp = NULL;&#xA;    size_t size = 0, index = 0;&#xA;    int ch = EOF;&#xA;&#xA;    while (ch) {&#xA;        ch = getc(stdin);&#xA;&#xA;        /* Check if we need to stop. */&#xA;        if (ch == EOF || ch == &#39;\n&#39;)&#xA;            ch = 0;&#xA;&#xA;        /* Check if we need to expand. */&#xA;        if (size &amp;lt;= index) {&#xA;            size += CHUNK;&#xA;            tmp = realloc(line, size);&#xA;            if (!tmp) {&#xA;                free(line);&#xA;                line = NULL;&#xA;                break;&#xA;            }&#xA;            line = tmp;&#xA;        }&#xA;&#xA;        /* Actually store the thing. */&#xA;        line[index++] = ch;&#xA;    }&#xA;&#xA;    return line;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There is a very good blog post that covers the steps in detail here: &lt;a href=&#34;https://brennan.io/2015/01/16/write-a-shell-in-c/&#34; target=&#34;_blank&#34;&gt;https://brennan.io/2015/01/16/write-a-shell-in-c/&lt;/a&gt;. It&amp;rsquo;s effectively the same implementation (in principle), except for the use of &lt;code&gt;getchar&lt;/code&gt; vs &lt;code&gt;getc&lt;/code&gt; (the former can only read from stdin, whereas &lt;code&gt;getc&lt;/code&gt; can read from any input stream).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#define LSH_RL_BUFSIZE 1024&#xA;char *lsh_read_line(void)&#xA;{&#xA;  int bufsize = LSH_RL_BUFSIZE;&#xA;  int position = 0;&#xA;  char *buffer = malloc(sizeof(char) * bufsize);&#xA;  int c;&#xA;&#xA;  if (!buffer) {&#xA;    fprintf(stderr, &amp;quot;lsh: allocation error\n&amp;quot;);&#xA;    exit(EXIT_FAILURE);&#xA;  }&#xA;&#xA;  while (1) {&#xA;    // Read a character&#xA;    c = getchar();&#xA;&#xA;    // If we hit EOF, replace it with a null character and return.&#xA;    if (c == EOF || c == &#39;\n&#39;) {&#xA;      buffer[position] = &#39;\0&#39;;&#xA;      return buffer;&#xA;    } else {&#xA;      buffer[position] = c;&#xA;    }&#xA;    position++;&#xA;&#xA;    // If we have exceeded the buffer, reallocate.&#xA;    if (position &amp;gt;= bufsize) {&#xA;      bufsize += LSH_RL_BUFSIZE;&#xA;      buffer = realloc(buffer, bufsize);&#xA;      if (!buffer) {&#xA;        fprintf(stderr, &amp;quot;lsh: allocation error\n&amp;quot;);&#xA;        exit(EXIT_FAILURE);&#xA;      }&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice &lt;code&gt;c&lt;/code&gt; variable is declared as an &lt;code&gt;int&lt;/code&gt; and not a &lt;code&gt;char&lt;/code&gt;, the author of the blog post makes mention of this as being because &lt;code&gt;EOF&lt;/code&gt; is an &lt;code&gt;int&lt;/code&gt; type&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The author then goes on to explain that in more recent releases, there is a much shorter version that can be implemented thanks to the &lt;code&gt;getline&lt;/code&gt; function:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;char *lsh_read_line(void)&#xA;{&#xA;  char *line = NULL;&#xA;  ssize_t bufsize = 0; // have getline allocate a buffer for us&#xA;  getline(&amp;amp;line, &amp;amp;bufsize, stdin);&#xA;  return line;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;function-prototypes&#34;&gt;Function Prototypes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A compiler will error if you try to call a function before it has been defined. This can be mitigated by utilising function prototypes that let you define the signature of the function up front and defer the definition until a later point in time (sort of like defining an interface type):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Function prototypes&#xA;int Foo(double data_values[], size_t count);&#xA;int Bar(double *x, size_t n);&#xA;&#xA;int main(void) {&#xA;  int f = Foo(...signature...);&#xA;  int b = Bar(...signature...)&#xA;}&#xA;&#xA;// Definitions for Foo() and Bar()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So that covers most of what I found interesting about C over the last few days. I&amp;rsquo;m not planning on writing any C code in the future (why bother when I can get pretty compariable performance + great tooling etc etc with a language like &lt;a href=&#34;https://golang.org&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But regardless, this was a fun little exercise in learning something new. Hope you learnt something too. As always, feel free to &lt;a href=&#34;https://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;ping me on twitter&lt;/a&gt; if you feel I&amp;rsquo;ve missed something.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/concepts-from-the-c-programming-language/</guid>
      <link>https://www.integralist.co.uk/posts/concepts-from-the-c-programming-language/</link>
      <pubDate>Mon, 28 Nov 2016 00:00:00 +0000</pubDate>
      <title>Concepts From the C Programming Language</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Your operating system provides manual pages that explain what specific commands do and where they can be located on your computer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most of us are at least familiar with opening a terminal and typing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man &amp;lt;some_command&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But you might be confused, when you see a manual page informing you to check out &lt;code&gt;&amp;lt;another_command&amp;gt;(2)&lt;/code&gt;. For example, you might be shown the message at the end of a man page that says &lt;code&gt;See also: chmod(2)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you try that, it won&amp;rsquo;t work:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man chmod(2)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s understand why that is and what it means.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;sections&#34;&gt;Sections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So the manual pages are separated into &amp;lsquo;sections&amp;rsquo;. This is what the number within the parentheses represents (i.e. &lt;code&gt;chmod(2)&lt;/code&gt; represents the &lt;code&gt;chmod&lt;/code&gt; command from section 2 of the OS manual).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To find where your manual pages are stored:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cd /usr/share/man&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;A simple &lt;code&gt;ls&lt;/code&gt; will show that on my OS (macOS) I have nine manuals:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man1/   man2/   man3/   man4/   man5/   man6/   man7/   man8/   man9/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Each manual section has an introduction page † that explains what the section covers. These (taken from my OS) are as follows:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;man1: introduction to general commands (tools and utilities)&lt;/li&gt;&#xA;&lt;li&gt;man2: introduction to system calls and error numbers&lt;/li&gt;&#xA;&lt;li&gt;man3: introduction to the C libraries&lt;/li&gt;&#xA;&lt;li&gt;man4: contains documentation on special files and sockets&lt;/li&gt;&#xA;&lt;li&gt;man5: introduction to file formats&lt;/li&gt;&#xA;&lt;li&gt;man6: contains documentation about games and other miscellaneous fun programs&lt;/li&gt;&#xA;&lt;li&gt;man7: miscellaneous information pages&lt;/li&gt;&#xA;&lt;li&gt;man8: introduction to system maintenance and operation commands&lt;/li&gt;&#xA;&lt;li&gt;man9: introduction to system kernel interfaces&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† except for manual sections 4 and 6. I had to go to the online reference for &lt;a href=&#34;https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/&#34; target=&#34;_blank&#34;&gt;macOS&lt;/a&gt; in order to find out what they contained&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you wanted to know &amp;lsquo;at a glance&amp;rsquo; what commands were available, then you could install the &lt;code&gt;tree&lt;/code&gt; command and execute it at the current directory (&lt;code&gt;/usr/share/man&lt;/code&gt;) and this would show you something like the following (cut short for brevity):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── man1&#xA;│   ├── ab.1&#xA;│   ├── accesstool.1&#xA;│   ├── addftinfo.1&#xA;│   ├── afconvert.1&#xA;│   ├── afhash.1&#xA;│   ├── afida.1&#xA;│   ├── afinfo.1&#xA;├── man2&#xA;│   ├── accept.2&#xA;│   ├── access.2&#xA;│   ├── acct.2&#xA;│   ├── adjtime.2&#xA;│   ├── aio_cancel.2&#xA;│   ├── aio_error.2&#xA;│   ├── aio_read.2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;sub-sections&#34;&gt;Sub sections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that most page files within each manual section have an extension that matches the section they&amp;rsquo;re contained within (e.g. &lt;code&gt;ab.1&lt;/code&gt; for &lt;code&gt;ab&lt;/code&gt; command inside manual 1 or &lt;code&gt;aio_read.2&lt;/code&gt; for &lt;code&gt;aio_read&lt;/code&gt; command inside manual 2).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s interesting is that there are some files, such as &lt;code&gt;httpdstat.d.1m&lt;/code&gt; (which is inside manual section 1) that have a different extension (&lt;code&gt;d.1m&lt;/code&gt;) or &lt;code&gt;asn1parse.1ssl&lt;/code&gt; (&lt;code&gt;1ssl&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By looking back at the &lt;a href=&#34;https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/&#34; target=&#34;_blank&#34;&gt;online macOS manual pages reference&lt;/a&gt; I noticed there were additional sub sections:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 1m&lt;/u&gt;: contains documentation for tools built on top of DTrace&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 1ssl&lt;/u&gt;: contains documentation on tools that are part of OpenSSL&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 1tcl&lt;/u&gt;: contains documentation on tools that are part of Tcl&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3cc&lt;/u&gt;: contains documentation on the Common Crypto API&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3pcap&lt;/u&gt;: contains documentation on the packet capture library, libpcap&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3pm&lt;/u&gt;: contains documentation on Perl modules&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3ssl&lt;/u&gt;: contains documentation on OpenSSL C library routines&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3tcl&lt;/u&gt;: contains documentation on Tcl/Tk C library routines&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 3x&lt;/u&gt;: contains documentation on curses-related C library routines&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 5ssl&lt;/u&gt;: contains documentation on SSL-specific configuration file formats&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section 7ssl&lt;/u&gt;: miscellaneous SSL documentation section&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section n&lt;/u&gt;: contains documentation about Tcl/Tk&lt;/li&gt;&#xA;&lt;li&gt;&lt;u&gt;Section ntcl&lt;/u&gt;: contains documentation about Tcl/Tk&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;accessing-different-sections&#34;&gt;Accessing different sections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Typically when we type &lt;code&gt;man &amp;lt;some_command&amp;gt;&lt;/code&gt;, the &lt;code&gt;man&lt;/code&gt; command will search all the sections looking for the specified command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It stops at the first match it finds. So there could be a scenario where you search for a command and you get the user space (top-level) entry command and not the &amp;lsquo;system call&amp;rsquo; version that actually interacts with your OS.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;chmod&lt;/code&gt; command is a good example of that scenario.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to see the actual system call manual page for &lt;code&gt;chmod&lt;/code&gt;, you need to search inside the specific section (which in this case is 2):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man 2 chmod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively, you can search multiple specific sections:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man -S 1:2 chmod&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above command will search through only sections 1 and 2, but it will still stop at the first match it finds so the above command is no different in outcome than just &lt;code&gt;man chmod&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if you know for sure that the command you&amp;rsquo;re looking for is somewhere within either the system call or C library manual pages, then &lt;code&gt;man -S 2:3 &amp;lt;your_command&amp;gt;&lt;/code&gt; would prevent a command from manual section 1 getting matched first.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to see the intro page for a section use &lt;code&gt;man &amp;lt;n&amp;gt; intro&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;searching-by-phrase&#34;&gt;Searching by phrase&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In case you&amp;rsquo;re unsure where to find a specific piece of information, you can use the &lt;code&gt;-K&lt;/code&gt; flag which will search &lt;em&gt;all&lt;/em&gt; manuals for the given search term/phrase. This can be slow, so it&amp;rsquo;s best to also provide a manual to scope the search down to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, I wanted to lookup &lt;code&gt;refspec&lt;/code&gt; in the git manual. I didn&amp;rsquo;t know where to look so I ran the following lookup:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man -K &amp;quot;refspec&amp;quot; git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This then presented a manual name along with the options of &lt;code&gt;y/n/q&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I type &lt;code&gt;y&lt;/code&gt; then the listed manual page would be opened. Once I &amp;lsquo;quit&amp;rsquo; the page (e.g. &lt;code&gt;q&lt;/code&gt;) then the next manual page found to contain the phrase &lt;code&gt;refspec&lt;/code&gt; would be listed along with the &lt;code&gt;y/n/q&lt;/code&gt; options. Anytime you want to stop going through the list of matches, you type &lt;code&gt;q&lt;/code&gt;.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/man-pages/</guid>
      <link>https://www.integralist.co.uk/posts/man-pages/</link>
      <pubDate>Fri, 25 Nov 2016 00:00:00 +0000</pubDate>
      <title>Understanding Man Pages</title>
    </item>
    <item>
      <description>&lt;p&gt;This post is aimed at explaining the difference between a system call (provided by the Linux kernal) and a wrapper function that has a similar name within one of the C standard libraries.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have no formal Computer Science (CS) background, I started programming in 1999 and only from 2016 am I starting to learn the C programming language in order to help give me a deeper knowledge of how *nix systems work and other core CS concepts.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See my previous post called &amp;lsquo;&lt;a href=&#34;/posts/bits-and-bytes/&#34;&gt;Bits and Bytes)&lt;/a&gt;&amp;rsquo; to see where these learnings are taking me.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;what-s-the-issue&#34;&gt;What&amp;rsquo;s the issue?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be confusing sometimes knowing where to look for documentation when dealing with C †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† that is if you&amp;rsquo;re not a systems engineer, and have no CS degree, nor learnt C&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;As an example, you might learn about the &lt;code&gt;strace&lt;/code&gt; command and start investigating what your Ruby application is up to. In doing so you&amp;rsquo;ll see lots of calls to different functions and you might decide you want to look up the documentation for those functions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This could be where your first problem arises. You might think &amp;ldquo;Ruby is written in C, so I&amp;rsquo;ll look at the C documentation&amp;rdquo; and then come up with nothing.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;so-what-s-going-on&#34;&gt;So what&amp;rsquo;s going on?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The key is to remember that the Linux operating system (which your code is very likely running on) is itself written in C. But Linux provides its own set of functions written in C that aren&amp;rsquo;t part of the C language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So you might see a function used and wonder why it&amp;rsquo;s not showing up within the C language documentation. That&amp;rsquo;s because it&amp;rsquo;s not part of the C language. The Linux engineers would&amp;rsquo;ve created the function within Linux so you need to look at the Linux documentation to find out what it does.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;e.g &lt;a href=&#34;https://linux.die.net/man/&#34; target=&#34;_blank&#34;&gt;https://linux.die.net/man/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Some of these Linux provided functions are known as &amp;lsquo;system calls&amp;rsquo;. If you visit &lt;a href=&#34;https://linux.die.net/man/&#34; target=&#34;_blank&#34;&gt;the above link&lt;/a&gt; you&amp;rsquo;ll see there in &amp;lsquo;section 2&amp;rsquo; a list of all system calls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An alternative (searchable) list of syscalls can be found here: &lt;a href=&#34;https://filippo.io/linux-syscall-table/&#34; target=&#34;_blank&#34;&gt;https://filippo.io/linux-syscall-table/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;wrapper-functions&#34;&gt;Wrapper functions?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now what makes this a little more confusing is that the system calls aren&amp;rsquo;t usually directly accessible. So &amp;lsquo;section 2&amp;rsquo; of the Linux documentation may list all the &amp;lsquo;system call&amp;rsquo; documentation, but &amp;lsquo;section 3&amp;rsquo; lists all library functions including what are referred to as &amp;lsquo;thin wrapper&amp;rsquo; functions for the system calls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, Linux uses a separate library that provides a &lt;code&gt;fork&lt;/code&gt; function which is a wrapper around the actual system call &lt;code&gt;fork&lt;/code&gt; equivalent provided by Linux itself. The wrapper function is then also something other applications written in C can utilise.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is noted here &lt;a href=&#34;https://linux.die.net/man/2/intro&#34; target=&#34;_blank&#34;&gt;https://linux.die.net/man/2/intro&lt;/a&gt; in the documentation:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A system call is an entry point into the Linux kernel. Usually, system calls are not invoked directly: instead, most system calls have corresponding C library wrapper functions which perform the steps required in order to invoke the system call. Thus, making a system call look the same as invoking a normal library function.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So what do these thin wrapper functions do? Well the docs tell us&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Often the glibc wrapper function is quite thin, doing little work other than copying arguments to the right registers before invoking the system call, and then setting errno appropriately after the system call has returned. Note: system calls indicate a failure by returning a negative error number to the caller; when this happens, the wrapper function negates the returned error number (to make it positive), copies it to errno, and returns -1 to the caller of the wrapper. Sometimes, however, the wrapper function does some extra work &lt;em&gt;before&lt;/em&gt; invoking the system call. For example, nowadays there are two related system calls, &lt;code&gt;truncate&lt;/code&gt; and &lt;code&gt;truncate64&lt;/code&gt;, and the glibc &lt;code&gt;truncate()&lt;/code&gt; wrapper function checks which of those system calls are provided by the kernel and determines which should be employed.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Using &lt;code&gt;fork&lt;/code&gt; as an example:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Here is the system call docs: &lt;a href=&#34;https://linux.die.net/man/2/fork&#34; target=&#34;_blank&#34;&gt;https://linux.die.net/man/2/fork&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Here is the wrapper docs: &lt;a href=&#34;https://linux.die.net/man/3/fork&#34; target=&#34;_blank&#34;&gt;https://linux.die.net/man/3/fork&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;But where do some of the wrapper equivalents come from? Well, one such provider is glibc; which is &lt;a href=&#34;https://en.wikipedia.org/wiki/GNU_C_Library&#34; target=&#34;_blank&#34;&gt;GNU&amp;rsquo;s standard C library&lt;/a&gt;. Which states:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The C language provides no built-in facilities for performing such common operations as input/output, memory management, string manipulation, and the like. Instead, these facilities are defined in a standard library, which you compile and link with your programs. The GNU C Library, described in this document, defines all of the library functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/C_standard_library&#34; target=&#34;_blank&#34;&gt;Here&amp;rsquo;s a link also to the standard C library&lt;/a&gt; libc if you&amp;rsquo;re interested.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;direct-system-call&#34;&gt;Direct system call?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What if one of the additional C libraries (libc, glibc etc) don&amp;rsquo;t provide a wrapper?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well in these situations you can make a direct system call!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See &lt;a href=&#34;https://linux.die.net/man/2/syscall&#34; target=&#34;_blank&#34;&gt;https://linux.die.net/man/2/syscall&lt;/a&gt; which states:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;syscall()&lt;/code&gt; is a small library function that invokes the system call whose assembly language interface has the specified number with the specified arguments. Employing &lt;code&gt;syscall()&lt;/code&gt; is useful, for example, when invoking a system call that has no wrapper function in the C library.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/c-and-syscalls/</guid>
      <link>https://www.integralist.co.uk/posts/c-and-syscalls/</link>
      <pubDate>Fri, 18 Nov 2016 00:00:00 +0000</pubDate>
      <title>Syscalls and C</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So this is a bit of a random journey through some different computer based subjects. Things that I felt I should try to better understand. Some of it will be very basic, but hopefully it&amp;rsquo;ll be useful to those who are new to tech, and are interested in learning these things (or old dogs like me who should know better).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bit&#34;&gt;Bit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The word &lt;em&gt;bit&lt;/em&gt; is short for &lt;em&gt;binary digit&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A bit is either a &lt;code&gt;1&lt;/code&gt; (true) or a &lt;code&gt;0&lt;/code&gt; (false).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Computers only understand the binary format (i.e. base-2)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;We discuss &amp;lsquo;base&amp;rsquo; numbers &lt;a href=&#34;#8&#34;&gt;below&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;byte&#34;&gt;Byte&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A grouping of eight &lt;em&gt;bits&lt;/em&gt; is called a &lt;em&gt;byte&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Read the next section to realise why I mention this tidbit of information&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;ram&#34;&gt;RAM&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The word &lt;em&gt;ram&lt;/em&gt; is an acronym for &lt;em&gt;random access memory&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s non-persistent memory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning it is lost when your machine is restarted, and persists only for the lifetime of the program using it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;RAM consists of bits, but each &lt;em&gt;segment&lt;/em&gt; of memory is actually a grouping of eight bits (which we already know is called a &lt;em&gt;byte&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in short we would say RAM is made up of bytes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Bytes are uniquely numbered to allow easy lookup of their contents.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A byte&amp;rsquo;s unique number is also referred to as its &lt;em&gt;address&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bit-and-ram-visualisation&#34;&gt;Bit and RAM Visualisation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/bits-visualised.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/bits-visualised.png&#34; alt=&#34;bits visualised&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see that each bit has an associated value which is calculated using the power of base-2 (we&amp;rsquo;ll cover &lt;a href=&#34;#8&#34;&gt;base numbers&lt;/a&gt; shortly).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;2&lt;sup&gt;0&lt;/sup&gt; = 1&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;1&lt;/sup&gt; = 2&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;2&lt;/sup&gt; = 4 (i.e. &lt;code&gt;2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;3&lt;/sup&gt; = 8 (i.e. &lt;code&gt;2 * 2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;4&lt;/sup&gt; = 16 (i.e. &lt;code&gt;2 * 2 * 2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;5&lt;/sup&gt; = 32 (i.e. &lt;code&gt;2 * 2 * 2 * 2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;6&lt;/sup&gt; = 64 (i.e. &lt;code&gt;2 * 2 * 2 * 2 * 2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;2&lt;sup&gt;7&lt;/sup&gt; = 128 (i.e. &lt;code&gt;2 * 2 * 2 * 2 * 2 * 2 * 2&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;With this information we can identify the value assigned by adding up the numbers associated with the ones and zeros.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in the image we can see four of the bits are given &lt;code&gt;1&lt;/code&gt; (on) and the rest are &lt;code&gt;0&lt;/code&gt; (off), meaning if we add up all the associated values of the bits that are &amp;lsquo;on&amp;rsquo; we get &lt;code&gt;99&lt;/code&gt; (e.g. &lt;code&gt;64 + 32 + 2 + 1&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;basic-bit-operators&#34;&gt;Basic Bit Operators&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You may have seen bit operators like &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; or &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; and wondered what they mean (generally referred to as &amp;lsquo;bitwise operators&amp;rsquo;). Essentially they manipulate bits.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some examples:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;64 &amp;gt;&amp;gt; 1 = 32&#xA;1 &amp;lt;&amp;lt; 3 = 8&#xA;1 &amp;lt;&amp;lt; 7 = 128&#xA;1 &amp;lt;&amp;lt; 15 = 32768&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So if we keep in mind the earlier image of our 8 bits in a byte memory representation, and that each bit had its own value (as described above), we can see (for example) that if we started at &lt;code&gt;64&lt;/code&gt; and moved to the right by &lt;code&gt;1&lt;/code&gt; bit, the next bit would be the one assigned the value &lt;code&gt;32&lt;/code&gt;. Hence, &lt;code&gt;64 &amp;gt;&amp;gt; 1&lt;/code&gt; results in the value &lt;code&gt;32&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similarly, if we start with the bit value &lt;code&gt;1&lt;/code&gt; and move to the left by &lt;code&gt;15&lt;/code&gt; bits we&amp;rsquo;ll get back the result of &lt;code&gt;32768&lt;/code&gt; because although we&amp;rsquo;ve only shown eight bit spaces above, you can just keep moving to the left (&lt;code&gt;64 * 2 = 128&lt;/code&gt;, &lt;code&gt;128 * 2 = 256&lt;/code&gt;, now keep going seven more places until you reach the fifteenth bit&amp;hellip; &lt;code&gt;256 * 2 = 512&lt;/code&gt;, &lt;code&gt;512 * 2 = 1024&lt;/code&gt;, &lt;code&gt;1024 * 2 = 2048&lt;/code&gt;, &lt;code&gt;2048 * 2 = 4096&lt;/code&gt;, &lt;code&gt;4096 * 2 = 8192&lt;/code&gt;, &lt;code&gt;8192 * 2 = 16384&lt;/code&gt;, &lt;code&gt;16384 * 2 = 32768&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For more bitwise operators, refer to these posts: &lt;a href=&#34;https://wiki.python.org/moin/BitwiseOperators&#34; target=&#34;_blank&#34;&gt;https://wiki.python.org/moin/BitwiseOperators&lt;/a&gt; and &lt;a href=&#34;https://medium.com/learning-the-go-programming-language/bit-hacking-with-go-e0acee258827&#34; target=&#34;_blank&#34;&gt;https://medium.com/learning-the-go-programming-language/bit-hacking-with-go-e0acee258827&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bits-and-ascii&#34;&gt;Bits and ASCII&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;ASCII is a set of codes where each &amp;lsquo;code point&amp;rsquo; represents a textual character such as a &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;z&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each code point has an associated binary number. For example, &lt;code&gt;a&lt;/code&gt; has the binary number &lt;code&gt;0110 0001&lt;/code&gt; which if we add up the values associated with those specific bits we&amp;rsquo;ll find it&amp;rsquo;ll yield the code point number &lt;code&gt;97&lt;/code&gt;. In ASCII the character &lt;code&gt;a&lt;/code&gt; is code point &lt;code&gt;97&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bits-and-numbers&#34;&gt;Bits and Numbers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;1 kilobyte (or 1KB) is 1,024 bytes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;1,024 bytes is 8192 bits (&lt;code&gt;8192/8&lt;/code&gt; or &lt;code&gt;8*1024&lt;/code&gt;, whichever you prefer)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following explanation is taken from &amp;ldquo;Beginning C&amp;rdquo; by Apress Publishing&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You might be wondering why we don’t work with simpler, more rounded numbers, such as a thousand, or a million, or a billion. The reason is this: there are 1,024 numbers from 0 to 1,023, and 1,023 happens to be 10 bits that are all 1 in binary: 11 1111 1111, which is a very convenient binary value. So while 1,000 is a very convenient decimal value, it’s actually rather inconvenient in a binary machine—it’s 11 1110 1000, which is not exactly neat and tidy. The kilobyte (1,024 bytes) is therefore defined in a manner that’s convenient for your computer, rather than for you.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So if we add up &lt;code&gt;512+256+128+64+32+16+8+4+2+1&lt;/code&gt; (notice this takes the existing 8 bit calculation from the above image and continues it for another two bits) we get &lt;code&gt;1023&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;ips&#34;&gt;IPs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is an example IPv4 IP:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;216.27.61.137&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;IPv4 IPs are expressed in decimal format.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;IPv6 IPs are eight 4-character hexadecimal numbers,&lt;br&gt;&#xA;which represent 16 bits each (for a total of 128 bits)&lt;br&gt;&#xA;e.g. &lt;code&gt;2001:0db8:0a0b:12f0:0000:0000:0000:0001&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To translate the above IP into binary form (for the sake of a computer to process it), we could use the above visualisation image to help us. The end result of which would look like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;11011000.00011011.00111101.10001001&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which breaks down into:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;11011000&lt;/code&gt;: 128 + 64 + 16 + 8 = 216&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;00011011&lt;/code&gt;: 16 + 8 + 2 + 1 = 27&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;00111101&lt;/code&gt;: 32 + 16 + 8 + 4 + 1 = 61&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;10001001&lt;/code&gt;: 128 + 8 + 1 = 137&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This explains why each of the four numbers within the decimal formatted version (i.e. &lt;code&gt;216.27.61.137&lt;/code&gt;) are called octets, as they represent eight bits (or a &amp;lsquo;byte&amp;rsquo; as we learned earlier) when viewed in binary form.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This also explains why IPv4 IPs are considered 32-bit numbers, because if you add each of the bits together (i.e. the number of total bits, not the value assigned to each bit) you&amp;rsquo;ll find there are a total of 32 bits that make up the IP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each bit can have two different states (1 or zero), meaning the total number of potential combinations per octet can be either 28 or 256. Meaning each octet can contain a potential value between zero and 255. Meaning if we were to combine the four octets, we could potentially have 4,294,967,296 variations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see the decimal represenation of an IPv4 IP is made up of four base-10 numbers (216, 27, 61, 137). Where each of those four numbers represent the binary equivalent (216=11011000, 27=00011011, 61=00111101, 137=10001001), which is a base-2 representation of a byte (or octet).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re unsure of what base numbers are and how they work, then read on&amp;hellip;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;base-numbers&#34;&gt;Base Numbers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s worth quickly covering what base numbers are as they help us understand the other different protocols we use on a regular basis, such as binary and things like IPs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Any number can be represented in multiple ways using a different base numbering system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many numbering systems, but the typical ones we&amp;rsquo;re used to are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Base 10 (Decimal)&lt;/li&gt;&#xA;&lt;li&gt;Base 2 (Binary)&lt;/li&gt;&#xA;&lt;li&gt;Base 8 (Octal)&lt;/li&gt;&#xA;&lt;li&gt;Base 16 (Hexadecimal)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The standard number system we (as humans) are most familiar with is called base-10 and it consists of the following numbers:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0,1,2,3,4,5,6,7,8,9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice there are ten numbers, hence it is called the base-10 system&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If we were to look at a number like &lt;code&gt;66&lt;/code&gt;, then this would tell us the number is made up of 6 tens and six units.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These numbers (0-9) represent &amp;lsquo;whole numbers&amp;rsquo;, while in the base-10 system we can also use a decimal point to represent decimal fractions of a number (e.g. &lt;code&gt;1.2&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an image, credit to Jenny Eather, that helps us visualise this model:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/base-10-system.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/base-10-system.png&#34; alt=&#34;base 10 system&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;base number&amp;rsquo; is the number of numbers within the system. So base-10 has 10 numbers (0,1,2,3,4,5,6,7,8,9) whereas binary is base-2 because it uses two numbers only (0, 1).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to know the unit each number in a system represents (we&amp;rsquo;ll use base-10 as the example, thanks to the following visualisation credited to Jenny Eather), then you calculate this using the power of the base number.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/base-10.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/base-10.png&#34; alt=&#34;base 10&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, as per the above visualisation, we can see:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;10&lt;sup&gt;3&lt;/sup&gt;: &lt;code&gt;10*10*10&lt;/code&gt;: 1000 (thousands)&lt;/li&gt;&#xA;&lt;li&gt;10&lt;sup&gt;2&lt;/sup&gt;: &lt;code&gt;10*10&lt;/code&gt;: 100 (hundreds)&lt;/li&gt;&#xA;&lt;li&gt;10&lt;sup&gt;1&lt;/sup&gt;: &lt;code&gt;10&lt;/code&gt;: 10 (tens)&lt;/li&gt;&#xA;&lt;li&gt;10&lt;sup&gt;0&lt;/sup&gt;: &lt;code&gt;1&lt;/code&gt;: 1 (unit)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So in practical terms, if you have a number like &lt;code&gt;75&lt;/code&gt; and want to represent it as base-10:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;5 (10&lt;sup&gt;0&lt;/sup&gt;: 5 units)&lt;/li&gt;&#xA;&lt;li&gt;7 (10&lt;sup&gt;1&lt;/sup&gt;: 7 tens)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Similarly, if we had a number like &lt;code&gt;675&lt;/code&gt; and want to represent it as base-10:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;5 (10&lt;sup&gt;0&lt;/sup&gt;: 5 units)&lt;/li&gt;&#xA;&lt;li&gt;7 (10&lt;sup&gt;1&lt;/sup&gt;: 7 tens)&lt;/li&gt;&#xA;&lt;li&gt;6 (10&lt;sup&gt;2&lt;/sup&gt;: 6 hundreds)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You can indicate what base you wish to represent a number like so:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;n&lt;sub&gt;b&lt;/sub&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where &lt;code&gt;n&lt;/code&gt; is the number and &lt;code&gt;b&lt;/code&gt; is the base you wish to state it is in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;75&lt;sub&gt;10&lt;/sub&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the number &lt;code&gt;75&lt;/code&gt; and we&amp;rsquo;re stating the base it represents is &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is useful when you&amp;rsquo;ve converted a number like &lt;code&gt;75&lt;/code&gt; into a different base (let&amp;rsquo;s say base-8, which would be &lt;code&gt;113&lt;/code&gt;) and you want to give that number in the proper context to someone else. You could write it as 113&lt;sub&gt;8&lt;/sub&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;convert-base-10-into-base-2-8&#34;&gt;Convert Base-10 into Base-&lt;sup&gt;2&lt;/sup&gt;&amp;frasl;&lt;sub&gt;8&lt;/sub&gt;&lt;/h3&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the steps are the same for converting to base-2 and base-8&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s consider how to convert the number &lt;code&gt;75&lt;/code&gt; into another base, like base-8. To do so, follow these steps&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;divide the number (75) by the desired base (8) (take note of the remainder: 3)&lt;/li&gt;&#xA;&lt;li&gt;take the result (9) and do the same (i.e. divide by the base and take note of the remainder)&lt;/li&gt;&#xA;&lt;li&gt;keep doing this until the result of dividing the previous answer by the base is zero&lt;/li&gt;&#xA;&lt;li&gt;now write out the remainders bottom to top, and that&amp;rsquo;s the number in base-8&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;In long form this looks like this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;75 (number) / 8 (base) = 9 (rounded) with a remainder of 3&lt;/li&gt;&#xA;&lt;li&gt;9 (previous answer) / 8 (base) = 1 (rounded) with a remainder of 1&lt;/li&gt;&#xA;&lt;li&gt;1 (previous answer) / 8 (base) = 0 (rounded) with a remainder of 1&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Meaning 75 evaluated in base-8 would be &lt;code&gt;113&lt;/code&gt; (all the remainders concatenated together, &amp;lsquo;bottom up&amp;rsquo;)&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;convert-base-10-into-base-16&#34;&gt;Convert Base-10 into Base-16&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The algorithm for converting from base-10 into base-2 and base-8 works basically the same for converting into base-16. But there is one caveat whereby a remainder can be in the double digits, and apparently (for reasons I don&amp;rsquo;t completely understand) we don&amp;rsquo;t want that, and so the number system was designed to replace the six instances where this can occur (the remainders being: 10, 11, 12, 13, 14, 15) with a alpha-numeric equivalent:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;10-A&lt;/li&gt;&#xA;&lt;li&gt;11-B&lt;/li&gt;&#xA;&lt;li&gt;12-C&lt;/li&gt;&#xA;&lt;li&gt;13-D&lt;/li&gt;&#xA;&lt;li&gt;14-E&lt;/li&gt;&#xA;&lt;li&gt;15-F&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So if we want to convert 110&lt;sub&gt;10&lt;/sub&gt; into a hexadecimal, the outcome of the algorithm would be:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;110 (number) / 16 (base) = 6 (rounded) with a remainder of 14&lt;/li&gt;&#xA;&lt;li&gt;6 (previous answer) / 16 (base) = 0 (rounded) with a remainder of 6&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We know that we need to replace &lt;code&gt;14&lt;/code&gt; (a double digit remainder) with the letter &lt;code&gt;E&lt;/code&gt; (see above mapping).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning 110 evaluated in base-16 would be &lt;code&gt;6E&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s try it again, but with the number 411&lt;sub&gt;10&lt;/sub&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;411 (number) / 16 (base) = 25 (rounded) with a remainder of 11&lt;/li&gt;&#xA;&lt;li&gt;25 (previous answer) / 16 (base) = 1 (rounded) with a remainder of 9&lt;/li&gt;&#xA;&lt;li&gt;1 (previous answer) / 16 (base) = 0 (rounded) with a remainder of 1&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We know that we need to replace &lt;code&gt;11&lt;/code&gt; with the letter &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning 411 evaluated in base-16 would be &lt;code&gt;19B&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;convert-any-base-to-base-10&#34;&gt;Convert Any Base to Base-10&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What if you want to convert a base-8 number (let&amp;rsquo;s say &lt;code&gt;113&lt;/code&gt;, why not) into base-10? The algorithm is to multiple the individual numbers by their associated power of the base and then add the numbers together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here are the base-8 powers:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;3: 8&lt;sup&gt;0&lt;/sup&gt;&lt;/li&gt;&#xA;&lt;li&gt;1: 8&lt;sup&gt;1&lt;/sup&gt;&lt;/li&gt;&#xA;&lt;li&gt;1: 8&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;And here is the algorithm:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;3 x 8&lt;sup&gt;0&lt;/sup&gt; = 3&lt;/li&gt;&#xA;&lt;li&gt;1 x 8&lt;sup&gt;1&lt;/sup&gt; = 8 (i.e. &lt;code&gt;1*8&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;1 x 8&lt;sup&gt;2&lt;/sup&gt; = 64 (i.e. &lt;code&gt;1*(8 * 8)&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;3 + 8 + 64 = 75&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re dealing with base-16, then again it&amp;rsquo;s the same but the difference is you&amp;rsquo;re translating the letter back into the corresponding number.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s convert &lt;code&gt;19B&lt;/code&gt; from base-16 back into base-10:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;B x 16&lt;sup&gt;0&lt;/sup&gt; (11 x 16&lt;sup&gt;0&lt;/sup&gt;) = 11&lt;/li&gt;&#xA;&lt;li&gt;9 x 16&lt;sup&gt;1&lt;/sup&gt; = 144&lt;/li&gt;&#xA;&lt;li&gt;1 x 16&lt;sup&gt;2&lt;/sup&gt; = 256&lt;/li&gt;&#xA;&lt;li&gt;11 + 144 + 256 = 411&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s try one more conversion between base-16 to base-10. The number is &lt;code&gt;1A4&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;4 x 16&lt;sup&gt;0&lt;/sup&gt; = 4&lt;/li&gt;&#xA;&lt;li&gt;A x 16&lt;sup&gt;1&lt;/sup&gt; (10 x 16&lt;sup&gt;1&lt;/sup&gt;) = 160&lt;/li&gt;&#xA;&lt;li&gt;1 x 16&lt;sup&gt;2&lt;/sup&gt; = 256&lt;/li&gt;&#xA;&lt;li&gt;4 + 160 + 256 = 420&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;cidr&#34;&gt;CIDR&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A CIDR is a range of IP addresses. We can use our understanding of bits, bytes and octets to understand the format of a CIDR.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A CIDR typically resembles something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10.0.0.0/n&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where &lt;code&gt;n&lt;/code&gt; is given the value 8, 16, 24, or 32 and these represent each of the 8-bit blocks that make up the IP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we want an IP range between &lt;code&gt;10.0.0.0&lt;/code&gt; and &lt;code&gt;10.255.255.255&lt;/code&gt;, we&amp;rsquo;d specify the CIDR as &lt;code&gt;10.0.0.0/8&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What &lt;code&gt;8&lt;/code&gt; states is that the last 8 bits of the 32-bit number is accounted for (this being the &lt;code&gt;10&lt;/code&gt; we&amp;rsquo;ve specified in our example). Meaning the rest of the 8-bit segments can be added up to their max of 255 (meaning the last IP in this CIDR range would be &lt;code&gt;10.255.255.255&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similarly if we want an IP range between &lt;code&gt;10.0.0.0&lt;/code&gt; and &lt;code&gt;10.0.255.255&lt;/code&gt;, we&amp;rsquo;d specify the CIDR as &lt;code&gt;10.0.0.0/16&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, &lt;code&gt;16&lt;/code&gt; states that the next 8-bits segment of the 32-bit number is now accounted for (this being the &lt;code&gt;0&lt;/code&gt; we&amp;rsquo;ve specified in our example &lt;code&gt;10.0&lt;/code&gt;). Meaning the rest of the 8-bit segments can be added up to their max of 255 (meaning the last IP in this CIDR range would be &lt;code&gt;10.0.255.255&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And so on&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;10.0.0.0/24&lt;/code&gt; gives us an ip range of &lt;code&gt;10.0.0.0&lt;/code&gt; to &lt;code&gt;10.0.0.255&lt;/code&gt; (256 IPs).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whereas &lt;code&gt;10.0.0.0/32&lt;/code&gt; gives us an ip range of 1 ip (&lt;code&gt;10.0.0.0&lt;/code&gt; to &lt;code&gt;10.0.0.0&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can use a tool such as &lt;a href=&#34;http://www.ipaddressguide.com/cidr&#34; target=&#34;_blank&#34;&gt;http://www.ipaddressguide.com/cidr&lt;/a&gt; to help you generate CIDRs&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can use the earlier &lt;a href=&#34;#visualisation&#34;&gt;byte visualisation&lt;/a&gt; table matrix to help us manually calculate a CIDR range.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve reproduced it below with a HTML table:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll likely need to scroll to the right to see the start of the 32-bit&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;table border=&#34;1&#34; id=&#34;table10&#34; bordercolor=&#34;#000080&#34; style=&#34;text-align: center; font-family: Verdana; font-size: 8pt; color: #000000&#34;&gt;&#xA;  &lt;tbody&gt;&#xA;  &lt;tr&gt;&#xA;      &lt;th width=&#34;15%&#34;&gt;IP&lt;/th&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;10&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;0&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;0&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;1&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;8 Bit Blocks&lt;/th&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;8 bits [24-31]&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;8 bits [16-23]&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;8 bits [08-15]&lt;/td&gt;&#xA;      &lt;td colspan=&#34;8&#34;&gt;8 bits [00-07]&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;32 Bit #&lt;/th&gt;&#xA;      &lt;td&gt;31&lt;/td&gt;&#xA;      &lt;td&gt;30&lt;/td&gt;&#xA;      &lt;td&gt;29&lt;/td&gt;&#xA;      &lt;td&gt;28&lt;/td&gt;&#xA;      &lt;td&gt;27&lt;/td&gt;&#xA;      &lt;td&gt;26&lt;/td&gt;&#xA;      &lt;td&gt;25&lt;/td&gt;&#xA;      &lt;td&gt;24&lt;/td&gt;&#xA;      &lt;td&gt;23&lt;/td&gt;&#xA;      &lt;td&gt;22&lt;/td&gt;&#xA;      &lt;td&gt;21&lt;/td&gt;&#xA;      &lt;td&gt;20&lt;/td&gt;&#xA;      &lt;td&gt;19&lt;/td&gt;&#xA;      &lt;td&gt;18&lt;/td&gt;&#xA;      &lt;td&gt;17&lt;/td&gt;&#xA;      &lt;td&gt;16&lt;/td&gt;&#xA;      &lt;td&gt;15&lt;/td&gt;&#xA;      &lt;td&gt;14&lt;/td&gt;&#xA;      &lt;td&gt;13&lt;/td&gt;&#xA;      &lt;td&gt;12&lt;/td&gt;&#xA;      &lt;td&gt;11&lt;/td&gt;&#xA;      &lt;td&gt;10&lt;/td&gt;&#xA;      &lt;td&gt;09&lt;/td&gt;&#xA;      &lt;td&gt;08&lt;/td&gt;&#xA;      &lt;td&gt;07&lt;/td&gt;&#xA;      &lt;td&gt;06&lt;/td&gt;&#xA;      &lt;td&gt;05&lt;/td&gt;&#xA;      &lt;td&gt;04&lt;/td&gt;&#xA;      &lt;td&gt;03&lt;/td&gt;&#xA;      &lt;td&gt;02&lt;/td&gt;&#xA;      &lt;td&gt;01&lt;/td&gt;&#xA;      &lt;td&gt;00&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Decimal&lt;/th&gt;&#xA;      &lt;td&gt;128&lt;/td&gt;&#xA;      &lt;td&gt;64&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;16&lt;/td&gt;&#xA;      &lt;td&gt;8&lt;/td&gt;&#xA;      &lt;td&gt;4&lt;/td&gt;&#xA;      &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;td&gt;128&lt;/td&gt;&#xA;      &lt;td&gt;64&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;16&lt;/td&gt;&#xA;      &lt;td&gt;8&lt;/td&gt;&#xA;      &lt;td&gt;4&lt;/td&gt;&#xA;      &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;td&gt;128&lt;/td&gt;&#xA;      &lt;td&gt;64&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;16&lt;/td&gt;&#xA;      &lt;td&gt;8&lt;/td&gt;&#xA;      &lt;td&gt;4&lt;/td&gt;&#xA;      &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;td&gt;1&lt;/td&gt;&#xA;      &lt;td&gt;128&lt;/td&gt;&#xA;      &lt;td&gt;64&lt;/td&gt;&#xA;      &lt;td&gt;32&lt;/td&gt;&#xA;      &lt;td&gt;16&lt;/td&gt;&#xA;      &lt;td&gt;8&lt;/td&gt;&#xA;      &lt;td&gt;4&lt;/td&gt;&#xA;      &lt;td&gt;2&lt;/td&gt;&#xA;      &lt;td&gt;1&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Binary&lt;/th&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;&lt;font color=&#34;#DC143C&#34;&gt;1&lt;/font&gt;&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;&lt;font color=&#34;#DC143C&#34;&gt;1&lt;/font&gt;&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;0&lt;/td&gt;&#xA;      &lt;td&gt;&lt;font color=&#34;#DC143C&#34;&gt;1&lt;/font&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There you go. A whirlwind ride through different basic computer tech topics. As always, if I&amp;rsquo;ve gotten anything wrong then just let me know on twitter.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/bits-and-bytes/</guid>
      <link>https://www.integralist.co.uk/posts/bits-and-bytes/</link>
      <pubDate>Wed, 16 Nov 2016 00:00:00 +0000</pubDate>
      <title>Bits and Bytes</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m guessing that you have an app like &lt;a href=&#34;https://1password.com/&#34; target=&#34;_blank&#34;&gt;1Password&lt;/a&gt; or &lt;a href=&#34;https://www.keepassx.org/&#34; target=&#34;_blank&#34;&gt;KeePassX&lt;/a&gt; to manage your passwords and other login credentials and you&amp;rsquo;re now looking for a cheaper alternative, and also one that doesn&amp;rsquo;t rely on a GUI (although as you&amp;rsquo;ll see that&amp;rsquo;s still possible).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If so, then &amp;ldquo;&lt;a href=&#34;https://www.passwordstore.org/&#34; target=&#34;_blank&#34;&gt;Pass&lt;/a&gt;&amp;rdquo; might be something of interest to you as it offers you the ability to securely store information via the command line interface (e.g. terminal shell) and is a free solution to that particular problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you need to be aware that it&amp;rsquo;s not as feature rich as far as something like 1Password is concerned.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, 1Password has browser extensions and native apps that allow you to automatically pull your password from 1Password directly into the relevant login fields of the service you&amp;rsquo;re visiting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pass is much simpler than that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the plus side, Pass is based on standardised unix technology. Specifically &lt;a href=&#34;https://www.gnupg.org/&#34; target=&#34;_blank&#34;&gt;GPG&lt;/a&gt;, which can give you confidence in the security mechanisms being utilised.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you need a refresher on encryption and GPG, then I&amp;rsquo;ll refer you to an &lt;a href=&#34;/posts/security-basics/&#34;&gt;earlier blog post of mine&lt;/a&gt; that covers the basics on this topic&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Installation on macOS is easy with &lt;a href=&#34;http://brew.sh/&#34; target=&#34;_blank&#34;&gt;Homebrew&lt;/a&gt;, and let&amp;rsquo;s face it, if you&amp;rsquo;re using macOS then Homebrew has become a de facto standard:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install pass&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once you&amp;rsquo;ve installed Pass you&amp;rsquo;ll probably want to install the shell auto-complete script as well. This requires you sourcing it into your shell profile.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me on Bash this looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;source /usr/local/etc/bash_completion.d/password-store&amp;quot; &amp;gt;&amp;gt; ~/.bashrc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;other distros available on the &lt;a href=&#34;https://www.passwordstore.org/#download&#34; target=&#34;_blank&#34;&gt;Pass website&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;At this point you need to initialize Pass:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pass init &amp;quot;AB123C4D&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Just swap &lt;code&gt;AB123C4D&lt;/code&gt; for your own GPG id. You can find that information by executing the following GPG command to list out all your available keys:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --list-keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should see something like the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pub   1234A/AB123C4D&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Your GPG id is the bit after the forward slash: &lt;code&gt;AB123C4D&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;example-usage&#34;&gt;Example Usage&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So here&amp;rsquo;s the super quick run down on how to use Pass:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;pass&lt;/code&gt;: displays the structure of your information&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass generate Foo/bar 20&lt;/code&gt;: insert new record &amp;amp; auto-generate password&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass insert Foo/bar&lt;/code&gt;: insert new record &amp;amp; manually enter password&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass insert Foo/bar -m&lt;/code&gt;: insert new record &amp;amp; manually enter multiline data&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass Foo/bar&lt;/code&gt;: display first line of data in stdout †&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass -c Foo/bar&lt;/code&gt;: copy first line of data into clipboard&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pass rm Foo/bar&lt;/code&gt;: remove the file &lt;code&gt;bar&lt;/code&gt; ∆&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;∆ to remove the whole directory: &lt;code&gt;pass rm -rf Foo&lt;/code&gt;&lt;br&gt;&#xA;Once the last file in a directory is removed, so is the directory&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So if you executed the second command (&lt;code&gt;generate&lt;/code&gt;) and &lt;em&gt;then&lt;/em&gt; executed the first command (&lt;code&gt;pass&lt;/code&gt;) you would see something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Password Store&#xA;└── Foo&#xA;    └── bar.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see we&amp;rsquo;ve created an arbitrary data structure of &lt;code&gt;Foo&lt;/code&gt; as the top level directory, and inside of that a encrypted file called &lt;code&gt;bar.gpg&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where we&amp;rsquo;ve specified † is an important point to be aware of, because you&amp;rsquo;re free to create any &amp;lsquo;structure&amp;rsquo; you like. So the suggestion from Pass is to create a single file that contains the following information (just as a guide):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Yw|ZSNH!}z&amp;quot;6{ym9pI&#xA;URL: *.amazon.com/*&#xA;Username: AmazonianChicken@example.com&#xA;Secret Question 1: What is your childhood best friend&#39;s most bizarre superhero fantasy?&#xA;Phone Support PIN #: 84719&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the first line is just the password, which means you can easily copy it to your clipboard using the &lt;code&gt;-c&lt;/code&gt; flag (e.g. &lt;code&gt;pass -c Foo/bar&lt;/code&gt;). All the remaining information is considered secondary meta data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other types of data structuring you could do is to store data in sub-directories, which would make it easier for copying into your clipboard. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Foo/app1/password&#xA;Foo/app1/secret-question&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively, you could store the password in one file, and have just a single additional metadata file like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Foo/app2&#xA;Foo/app2.meta&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;app2&lt;/code&gt; is the file containing the password, and &lt;code&gt;app2.meta&lt;/code&gt; is the file that contains all the other related information such as secret question/answer key pairs and contact numbers/emails etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But to be honest, that last style seems a bit pointless as having a &lt;code&gt;.meta&lt;/code&gt; file is still a manual process for copying out data (unless your metadata consists of one additional secret question password, which could be on the first line of that file for easy copying, and then all other data is contact numbers and things like that).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;exporting-data&#34;&gt;Exporting Data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you want to automate the migration of data out of a GUI based app such as 1Password, then the Pass community &lt;a href=&#34;https://www.passwordstore.org/#migration&#34; target=&#34;_blank&#34;&gt;has you covered&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;synchronisation&#34;&gt;Synchronisation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I wanted to be able to backup my encrypted password store, in case my laptop melted one day. So the simplest solution was to move the directory &lt;code&gt;~/.password-store&lt;/code&gt; into a cloud provider space for synchronisation and then symlinking the directory into my home directory:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ln -s ~/YourCloudOrg/.password-store/ ~/.password-store&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Yes this means that your encrypted data is now only as secure as the passphrase around your GPG private key. But I&amp;rsquo;m fairly confident in both my encryption key and the passphrase around it and so this is an acceptable compromise to make.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Security and Convenience, these two always dance around each other.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mobile-and-gui-applications&#34;&gt;Mobile and GUI Applications&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve no need for a desktop/laptop GUI, as that&amp;rsquo;s what the terminal shell is for and I&amp;rsquo;m happy using that. But if you check the introduction text on the Pass website, you&amp;rsquo;ll find details on some different community built GUIs that are available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are also mobile applications, which I&amp;rsquo;ve yet to try out because they seem like quite a bit of faff to set-up; and this is the biggest downside to Pass so far and it doesn&amp;rsquo;t work with synchronisation via a cloud provider.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead the Android app expects you to configure your Pass store to be a git repository (something I&amp;rsquo;ve not covered here). But then that requires you to push the store into a public/private git repo.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now there&amp;rsquo;s no reason why I couldn&amp;rsquo;t do this beause I&amp;rsquo;ve already conceded that security aspect when I exposed the files by syncing them to a cloud provider (a little less visible than a public git repo for some people), but again, if you&amp;rsquo;re confident in your key encryption and its passphrase then this might work fine for you.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;multifactor-authentication&#34;&gt;MultiFactor Authentication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The purpose of multifactor authentication (also known as 2FA: two factor authentication) is to add additional security to the process of accessing a service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, typically you&amp;rsquo;ll log into a service using a username and password. But if your laptop becomes compromised and you&amp;rsquo;ve saved your login credentials for a particular service then without 2FA you&amp;rsquo;ve now given up access to that service and the data it holds.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For some services, such as provided by Google, you can enable 2FA. What this means is that you associate with that service (let&amp;rsquo;s use Google as the example) another device.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most of the time the device is a mobile phone, as that is one of the few devices that are usually safely held by the true owner of the Google account being accessed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With 2FA you&amp;rsquo;ll be provided a token. You then store this token in a 2FA application (Google has its own &amp;ldquo;Authenticator&amp;rdquo; Android app for example). Now every time you go to log into your Google account from a new machine, you&amp;rsquo;ll be asked to consult the 2FA application (which will give you a random/unique key back). You&amp;rsquo;ll then be expected to provide Google the 2FA key along with your username and password.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can do a similar thing using Pass. But instead of a mobile device as the associated device to the Google account, you can associate your laptop running  Pass and a desktop equivalent 2FA application (remember, it doesn&amp;rsquo;t have to be your main laptop, it could be another laptop or computer obviously).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now this would normally be a bit of a concern for some people. The idea being that 2FA is supposed to help when your &amp;lsquo;device&amp;rsquo; is compromised. Hence people associate their mobile as the device for handling 2FA, as it&amp;rsquo;s less likely to get lost or damaged.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have your laptop, which has access to the service, also being the associated 2FA token provider kinda defeats the point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But because we&amp;rsquo;re using GPG and Pass, in effect (similar to my comments about sync&amp;rsquo;ing my Pass store onto a cloud provider), if you&amp;rsquo;re confident your generated GPG key and its passphrase are solid then you should be less concerned because your key will be near impossible to crack via automation and so if your laptop is compromised it won&amp;rsquo;t matter as the 2FA application won&amp;rsquo;t be able to pull the Google token from Pass in order to generate a unique key to access Google (along with your username and password).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way of achieving this was shared with me by &lt;a href=&#34;https://twitter.com/jakedchampion&#34; target=&#34;_blank&#34;&gt;Jake Champion&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install oath-toolkit&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will provide you with a &lt;code&gt;oath&lt;/code&gt; command, which will be used as your 2FA application. The way it works is that when setting up 2FA on your Google account, you&amp;rsquo;ll take the provided token and store it in Pass.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now every time you need to access your account, you can execute the following command and extract the Google token from Pass. Which will generate the key needed to be provided to Google when logging in using your username/password:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;oathtool --base32 --totp $(pass 2FA/Amazon)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above snippet assumes you stored your Google token like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pass insert 2FA/Amazon &amp;lt;your_google_token&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s all there is to it.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;a href=&#34;https://gist.github.com/NapoleonWils0n/4005467&#34; target=&#34;_blank&#34;&gt;this gist&lt;/a&gt; for more details on the Google 2FA setup process&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Compared to the pricing of something like 1Password:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$3 per month (forever)&lt;/li&gt;&#xA;&lt;li&gt;$64 (single licence, not all devices either and not all features)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Then considering I spend the majority of my time working from a terminal shell. It would seem that Pass is a good starting point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But ultimately I think I&amp;rsquo;m going to have to explore the git hosted option (with a private repository) for the mobile app setup, just so that I can ensure a little less visibility into my data information structure.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/terminal-password-manager/</guid>
      <link>https://www.integralist.co.uk/posts/terminal-password-manager/</link>
      <pubDate>Wed, 19 Oct 2016 00:00:00 +0000</pubDate>
      <title>Terminal Password Manager</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not all programmers need to get their hands dirty and have to dig deep into what exactly their applications or services are doing at a lower/network level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why programmers work with programming languages, as they provide a nice high-level abstraction layer that protects us from a lot of these concerns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But regardless if you&amp;rsquo;re a client-side developer or a server-side developer, at some point your application will start misbehaving and it can be useful to have experience using command-line/terminal based tools to help you debug what&amp;rsquo;s going on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That is what I want to briefly cover today: a few select programs that you may find useful to have in your debugging toolbox. I won&amp;rsquo;t claim to be an expert with any of these, but I&amp;rsquo;ve had to use these tools at some point or another so I at least know what I have available to me whenever things start going haywire.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;d encourage you to do follow-up reading once you&amp;rsquo;ve gone through this post, and to experiment with these tools if there are any in particular that you find interesting.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;agony-of-choice&#34;&gt;Agony of Choice&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;You are going to find that some of the tools I mention, have a lot of crossover behaviour between them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the main points of confusion for people, when given the choice of lots of different utility tools, is: when/why should I use this over another very similar tool?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The answer: it depends (as with everything in life).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sometimes it can just be a personal preference. You&amp;rsquo;re happy using tool x, which can sort of do that &amp;lsquo;thing&amp;rsquo; you need it to, but maybe tool x isn&amp;rsquo;t quite as good at showing you the &amp;lsquo;thing&amp;rsquo; as tool y (which was designed &lt;em&gt;specifically&lt;/em&gt; to solve the &amp;lsquo;thing&amp;rsquo; problem); but hey, tool x is good enough at it and it also allows me to inspect y and z problems (which are things I look at the majority of the time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Just be aware that that there will be crossover functionality, and that on occasions certain tools might only have &lt;em&gt;slight&lt;/em&gt; additions that could be useful to you depending on the problem you&amp;rsquo;re trying to debug.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;deprecated-commands&#34;&gt;Deprecated Commands?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;It was brought to my attention by &lt;a href=&#34;https://twitter.com/aidylewis&#34; target=&#34;_blank&#34;&gt;Aidy Lewis&lt;/a&gt; that tools such as &lt;code&gt;ifconfig&lt;/code&gt; and &lt;code&gt;netstat&lt;/code&gt; have since been deprecated in favour of other tools. See &lt;a href=&#34;https://dougvitale.wordpress.com/2011/12/21/deprecated-linux-networking-commands-and-their-replacements/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; for the details of what the replacement tools are.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;&#xA;&#xA;&lt;h2 id=&#34;tcp-and-http&#34;&gt;TCP and HTTP&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The fact is in order to use tools such as &lt;code&gt;tcpdump&lt;/code&gt;, &lt;code&gt;telnet&lt;/code&gt; or &lt;code&gt;netstat&lt;/code&gt; you do need to understand the basics of how the TCP and HTTP protocols work in order to utilise these programs fully.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As far as other tools are concerned, you may need to understand some networking basics. I mean, I know very little, but I know just &lt;em&gt;enough&lt;/em&gt; to muddle along when I need to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll be covering how I&amp;rsquo;ve used these tools but not really much more beyond that, so you may need to do some additional reading in order to appreciate what these tools offer (outside of my own experience with them).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;osi-model&#34;&gt;OSI Model&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Finally, before we get going, it&amp;rsquo;s worth taking a moment to consider the &lt;a href=&#34;https://en.wikipedia.org/wiki/OSI_model&#34; target=&#34;_blank&#34;&gt;OSI Model&lt;/a&gt;. What this model represents are the different layers of a system. From the very real hardware level (e.g. physical cables that make the interwebs work) right up to the software level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a table matrix that attempts to identify these &amp;lsquo;layers&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;table class=&#34;wikitable&#34; style=&#34;margin: 1em auto 1em auto;&#34;&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th colspan=&#34;5&#34;&gt;OSI Model&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th colspan=&#34;2&#34;&gt;Layer&lt;/th&gt;&#xA;      &lt;th&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Protocol_data_unit&#34; title=&#34;Protocol data unit&#34;&gt;Protocol data unit&lt;/a&gt; (PDU)&lt;/th&gt;&#xA;      &lt;th&gt;Function&lt;/th&gt;&#xA;      &lt;th&gt;Examples&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th rowspan=&#34;4&#34;&gt;Host&lt;br&gt;&#xA;        layers&lt;/th&gt;&#xA;      &lt;td style=&#34;background:#d8ec9b;&#34;&gt;7.&amp;nbsp;&lt;a href=&#34;https://en.wikipedia.org/wiki/Application_layer&#34; title=&#34;Application layer&#34;&gt;Application&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#d8ec9c;&#34; rowspan=&#34;3&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Data_(computing)&#34; title=&#34;Data (computing)&#34;&gt;Data&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#d8ec9c;&#34;&gt;&lt;small&gt;High-level &lt;a href=&#34;https://en.wikipedia.org/wiki/API&#34; class=&#34;mw-redirect&#34; title=&#34;API&#34;&gt;APIs&lt;/a&gt;, including resource sharing, remote file access&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/HTTP&#34; class=&#34;mw-redirect&#34; title=&#34;HTTP&#34;&gt;HTTP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_File_System&#34; title=&#34;Network File System&#34;&gt;NFS&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/FTP&#34; class=&#34;mw-redirect&#34; title=&#34;FTP&#34;&gt;FTP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Telnet&#34; title=&#34;Telnet&#34;&gt;Telnet&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/SMTP&#34; class=&#34;mw-redirect&#34; title=&#34;SMTP&#34;&gt;SMTP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Secure_Shell&#34; title=&#34;Secure Shell&#34;&gt;SSH&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td style=&#34;background:#d8ec9b;&#34;&gt;6.&amp;nbsp;&lt;a href=&#34;https://en.wikipedia.org/wiki/Presentation_layer&#34; title=&#34;Presentation layer&#34;&gt;Presentation&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#d8ec9b;&#34;&gt;&lt;small&gt;Translation of data between a networking service and an application; including &lt;a href=&#34;https://en.wikipedia.org/wiki/Character_encoding&#34; title=&#34;Character encoding&#34;&gt;character encoding&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Data_compression&#34; title=&#34;Data compression&#34;&gt;data compression&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Encryption&#34; title=&#34;Encryption&#34;&gt;encryption/decryption&lt;/a&gt;&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/S/MIME&#34; title=&#34;S/MIME&#34;&gt;S/MIME&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Transport_Layer_Security&#34; title=&#34;Transport Layer Security&#34;&gt;TLS&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td style=&#34;background:#d8ec9b;&#34;&gt;5. &lt;a href=&#34;https://en.wikipedia.org/wiki/Session_layer&#34; title=&#34;Session layer&#34;&gt;Session&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#d8ec9b;&#34;&gt;&lt;small&gt;Managing communication &lt;a href=&#34;https://en.wikipedia.org/wiki/Session_(computer_science)&#34; title=&#34;Session (computer science)&#34;&gt;sessions&lt;/a&gt;, i.e. continuous exchange of information in the form of multiple back-and-forth transmissions between two nodes&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Remote_Procedure_Call&#34; class=&#34;mw-redirect&#34; title=&#34;Remote Procedure Call&#34;&gt;RPC&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/DECnet&#34; title=&#34;DECnet&#34;&gt;SCP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Password_authentication_protocol&#34; class=&#34;mw-redirect&#34; title=&#34;Password authentication protocol&#34;&gt;PAP&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td style=&#34;background:#e7ed9c;&#34;&gt;4. &lt;a href=&#34;https://en.wikipedia.org/wiki/Transport_layer&#34; title=&#34;Transport layer&#34;&gt;Transport&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e7ed9c;&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Packet_segmentation&#34; title=&#34;Packet segmentation&#34;&gt;Segment&lt;/a&gt; (TCP) / &lt;a href=&#34;https://en.wikipedia.org/wiki/Datagram&#34; title=&#34;Datagram&#34;&gt;Datagram&lt;/a&gt; (UDP)&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e7ed9c;&#34;&gt;&lt;small&gt;Reliable transmission of data segments between points on a network, including &lt;a href=&#34;https://en.wikipedia.org/wiki/Packet_segmentation&#34; title=&#34;Packet segmentation&#34;&gt;segmentation&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)&#34; title=&#34;Acknowledgement (data networks)&#34;&gt;acknowledgement&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Multiplexing&#34; title=&#34;Multiplexing&#34;&gt;multiplexing&lt;/a&gt;&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Transmission_Control_Protocol&#34; title=&#34;Transmission Control Protocol&#34;&gt;TCP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/User_Datagram_Protocol&#34; title=&#34;User Datagram Protocol&#34;&gt;UDP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/NetBIOS_Frames_protocol&#34; title=&#34;NetBIOS Frames protocol&#34;&gt;NBF&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th rowspan=&#34;3&#34;&gt;Media&lt;br&gt;&#xA;        layers&lt;/th&gt;&#xA;      &lt;td style=&#34;background:#eddc9c;&#34;&gt;3. &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_layer&#34; title=&#34;Network layer&#34;&gt;Network&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#eddc9c;&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Network_packet&#34; title=&#34;Network packet&#34;&gt;Packet&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#eddc9c;&#34;&gt;&lt;small&gt;Structuring and managing a multi-node network, including &lt;a href=&#34;https://en.wikipedia.org/wiki/Address_space&#34; title=&#34;Address space&#34;&gt;addressing&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Routing&#34; title=&#34;Routing&#34;&gt;routing&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_traffic_control&#34; title=&#34;Network traffic control&#34;&gt;traffic control&lt;/a&gt;&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/IPv4&#34; title=&#34;IPv4&#34;&gt;IPv4&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/IPv6&#34; title=&#34;IPv6&#34;&gt;IPv6&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol&#34; title=&#34;Internet Control Message Protocol&#34;&gt;ICMP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/IPsec&#34; title=&#34;IPsec&#34;&gt;IPsec&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Connectionless_Network_Protocol&#34; class=&#34;mw-redirect&#34; title=&#34;Connectionless Network Protocol&#34;&gt;CLNP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/AppleTalk#Datagram_Delivery_Protocol&#34; title=&#34;AppleTalk&#34;&gt;DDP&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td style=&#34;background:#e9c189;&#34;&gt;2. &lt;a href=&#34;https://en.wikipedia.org/wiki/Data_link_layer&#34; title=&#34;Data link layer&#34;&gt;Data link&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e9c189;&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Frame_(networking)&#34; title=&#34;Frame (networking)&#34;&gt;Frame&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e9c189;&#34;&gt;&lt;small&gt;Reliable transmission of data frames between two nodes connected by a physical layer&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802.2&#34; title=&#34;IEEE 802.2&#34;&gt;IEEE 802.2&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/L2TP&#34; class=&#34;mw-redirect&#34; title=&#34;L2TP&#34;&gt;L2TP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/LLDP&#34; class=&#34;mw-redirect&#34; title=&#34;LLDP&#34;&gt;LLDP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Media_access_control&#34; title=&#34;Media access control&#34;&gt;IEEE 802 MAC layers&lt;/a&gt; (&lt;a href=&#34;https://en.wikipedia.org/wiki/Ethernet&#34; title=&#34;Ethernet&#34;&gt;Ethernet&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802.11&#34; title=&#34;IEEE 802.11&#34;&gt;IEEE 802.11&lt;/a&gt;, etc.), &lt;a href=&#34;https://en.wikipedia.org/wiki/Point-to-Point_Protocol&#34; title=&#34;Point-to-Point Protocol&#34;&gt;PPP&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Asynchronous_Transfer_Mode&#34; title=&#34;Asynchronous Transfer Mode&#34;&gt;ATM&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/Multiprotocol_Label_Switching&#34; title=&#34;Multiprotocol Label Switching&#34;&gt;MPLS&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td style=&#34;background:#e9988a;&#34;&gt;1. &lt;a href=&#34;https://en.wikipedia.org/wiki/Physical_layer&#34; title=&#34;Physical layer&#34;&gt;Physical&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e9988a;&#34;&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Bit&#34; title=&#34;Bit&#34;&gt;Bit&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;td style=&#34;background:#e9988a;&#34;&gt;&lt;small&gt;Transmission and reception of raw bit streams over a physical medium&lt;/small&gt;&lt;/td&gt;&#xA;      &lt;td&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/DOCSIS&#34; title=&#34;DOCSIS&#34;&gt;DOCSIS&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/DSL&#34; class=&#34;mw-redirect&#34; title=&#34;DSL&#34;&gt;DSL&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802&#34; title=&#34;IEEE 802&#34;&gt;IEEE 802&lt;/a&gt; physical layers (&lt;a href=&#34;https://en.wikipedia.org/wiki/Ethernet_physical_layer&#34; title=&#34;Ethernet physical layer&#34;&gt;Ethernet&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/IEEE_802.11&#34; title=&#34;IEEE 802.11&#34;&gt;IEEE 802.11&lt;/a&gt;, etc.), &lt;a href=&#34;https://en.wikipedia.org/wiki/ISDN&#34; class=&#34;mw-redirect&#34; title=&#34;ISDN&#34;&gt;ISDN&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/RS-232&#34; title=&#34;RS-232&#34;&gt;RS-232&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;!--&#xA;&lt;table&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;th&gt;&lt;/th&gt;&#xA;        &lt;th&gt;Layer&lt;/th&gt;&#xA;        &lt;th&gt;Protocols&lt;/th&gt;&#xA;        &lt;th&gt;Description&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;7.&lt;/td&gt;&#xA;        &lt;td&gt;Application&lt;/td&gt;&#xA;        &lt;td&gt;HTTP, FTP, SMTP&lt;/td&gt;&#xA;        &lt;td&gt;Window for user app processes&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;6.&lt;/td&gt;&#xA;        &lt;td&gt;Presentation&lt;/td&gt;&#xA;        &lt;td&gt;JPEG, GIF, MPEG&lt;/td&gt;&#xA;        &lt;td&gt;Format the data to be presented to the Application layer (network translator)&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;5.&lt;/td&gt;&#xA;        &lt;td&gt;Session&lt;/td&gt;&#xA;        &lt;td&gt;RPC, SQL, NFS&lt;/td&gt;&#xA;        &lt;td&gt;Allow session establishment between processes running on different stations&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;4.&lt;/td&gt;&#xA;        &lt;td&gt;Transport&lt;/td&gt;&#xA;        &lt;td&gt;TCP, UDP, SPX&lt;/td&gt;&#xA;        &lt;td&gt;Flow control, ensures all messages are delivered error-free, in sequence, no losses or duplications&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;3.&lt;/td&gt;&#xA;        &lt;td&gt;Network&lt;/td&gt;&#xA;        &lt;td&gt;IP, IPX, ICMP&lt;/td&gt;&#xA;        &lt;td&gt;Routers control operation of subnet, deciding physical path data takes&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;2.&lt;/td&gt;&#xA;        &lt;td&gt;Data Link&lt;/td&gt;&#xA;        &lt;td&gt;PPP/SLIP&lt;/td&gt;&#xA;        &lt;td&gt;Provides error-free transfer of data over physical layer&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;1.&lt;/td&gt;&#xA;        &lt;td&gt;Physical&lt;/td&gt;&#xA;        &lt;td&gt;Hub&lt;/td&gt;&#xA;        &lt;td&gt;Physical structure (cables, hubs etc)&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;&lt;/table&gt;&#xA;--&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll find many differing versions of the OSI Model (i.e. the layers described are always the same, but you may see more or less protocols defined depending on what version you look at), this is just one such version copied vertabim from Wikipedia&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason this is useful, is because you can identify which layer the relevant tools are operating at. Tools like &lt;code&gt;netstat&lt;/code&gt; operate at layer four (transport: &lt;code&gt;tcp&lt;/code&gt;), whereas &lt;code&gt;telnet&lt;/code&gt; operates at layer seven (application: it actually has its own protocol &lt;code&gt;telnet&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When debugging an issue, if you know the problem space is a particular layer of the OSI model, then you&amp;rsquo;ll have an easier time identifying which tool is best suited to the investigation.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;utilities&#34;&gt;Utilities&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are &lt;em&gt;many&lt;/em&gt; different utilities, some provided as built-ins to your OS, others might be &lt;a href=&#34;https://www.gnu.org/home.en.html&#34; target=&#34;_blank&#34;&gt;GNU&lt;/a&gt; flavoured or home grown (e.g. they can be built using a myriad of programming languages) and which you have to download separately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The ones listed below are a selection of tools I find particularly useful for different scenarios. But they&amp;rsquo;re not all available on the Mac OS (which is what I use, and which - I&amp;rsquo;m making a &lt;em&gt;massive&lt;/em&gt; assumption - you are likely using too).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I do provide basic installation instructions for some of the tools that aren&amp;rsquo;t available for the Mac OS (either natively or at all) and for those tools that aren&amp;rsquo;t available for &lt;em&gt;your&lt;/em&gt; OS, I would recommend using &lt;a href=&#34;https://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt; for testing them out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;d suggest for the purpose of this article to try one of the following if you don&amp;rsquo;t want/use Mac OS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run -it centos /bin/bash&#xA;&#xA;# or&#xA;&#xA;docker run -it ubuntu /bin/bash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Also, the usage between Mac OS and Linux can vary&lt;br&gt;&#xA;Example: &lt;code&gt;top -n&lt;/code&gt; on Mac shows only n number of items; Linux runs n number of ticks before stopping&lt;br&gt;&#xA;If you notice something different, then it&amp;rsquo;ll likely be the OS&lt;br&gt;&#xA;But ultimately the examples I give are for Mac OS (unless stated otherwise)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;With all that out of the way, let&amp;rsquo;s begin&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;top&#34;&gt;top&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: displays running processes with cpu and memory utilisation&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;top&lt;/code&gt; command displays processor activity and also displays tasks managed by the kernel in real-time. If you have a cluster of nodes that are setup to scale up based on either CPU or Memory usage, then your first starting point will be to jump onto a running instance and check the different processes running and what their consumption is.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Or maybe an application on your laptop is running very slowly? You can inspect its CPU consumption to see if it&amp;rsquo;s doing something odd and maxing out at 99%&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-top.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-top.jpg&#34; alt=&#34;shell top&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some basic commands:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;top -user &amp;lt;user&amp;gt;&lt;/code&gt;: filter processes by those run by specified user&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;e.g. &lt;code&gt;top -user $(who | awk &#39;NR==1 {print $1}&#39;)&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;top -n 10&lt;/code&gt;: stops command running after 10 intervals&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;otherwise runs forever or until &lt;code&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt; (&lt;code&gt;SIGINT&lt;/code&gt; &amp;ldquo;interrupt&amp;rdquo; signal received)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You can change which column controls the order display (the default being CPU) by typing &lt;code&gt;o&lt;/code&gt; and then typing the column name. For example:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;+command&lt;/code&gt;: order by the COMMAND column (ascending order)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-command&lt;/code&gt;: order by the COMMAND column (descending order)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;+&lt;/code&gt; is implied (so no need to type it)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The following key strokes can be executed whilst &lt;code&gt;top&lt;/code&gt; is running&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;z&lt;/code&gt;: toggles on/off ability to have currently running processes highlighted&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4 id=&#34;non-mac&#34;&gt;Non-Mac&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;On the non-Mac version of &lt;code&gt;top&lt;/code&gt; you may find that you need the output to show you the complete path to the running program (which can be handy if you don&amp;rsquo;t recognise the program, and want to know where it&amp;rsquo;s located):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;c&lt;/code&gt;: toggles on/off absolute path for the COMMAND&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Similarly for non-Mac versions you can dynamically change the refresh rate:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;d&lt;/code&gt;: change interval for screen/data refresh&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Finally one other useful thing for non-Mac versions is the ability to kill a process you don&amp;rsquo;t like the look of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;k&lt;/code&gt;: followed by PID of process you want to kill&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;1&lt;/code&gt;: toggles a breakdown of the CPU usage (rather than showing aggregated value)&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I mention the above non-Mac options because when debugging on a remote server, chances are you&amp;rsquo;ll need some of those details more.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Failing all that you could just install the man pages and double check the available options (or run a Docker container and double check them):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install man&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are also some pretty fancy alternatives, such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://hisham.hm/htop/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;brew install htop&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/MrRio/vtop&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;npm install -g vtop&lt;/code&gt;&lt;/a&gt; (node)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;ps&#34;&gt;ps&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: displays snapshot of running processes&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ps&lt;/code&gt; command is useful for seeing &amp;lsquo;at a glance&amp;rsquo; what process id&amp;rsquo;s have been provided to different programs and which user started them (as well as the relationship between processes).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Majority of the time you&amp;rsquo;ll use &lt;code&gt;ps&lt;/code&gt; just to identify the process id (&lt;code&gt;pid&lt;/code&gt;) so you can then utilise another tool for inspecting the relevant process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-ps.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-ps.jpg&#34; alt=&#34;shell ps&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The differences between &lt;code&gt;ps&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt; are subtle, both display details about active processes (albeit in different formats). But &lt;code&gt;top&lt;/code&gt; is continuous whereas &lt;code&gt;ps&lt;/code&gt; is just a snapshop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ps&lt;/code&gt; command also offers some more advanced display options, not just a table matrix, and these can help visualise the parent/children relationship for particular processes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some useful commands you can try:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ps aux&lt;/code&gt;: shows all running processes (even those without a tty or are not owned by you)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ps axjf&lt;/code&gt;: shows parent process (ppids) &amp;amp; nested children pids with tree formatting&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;f&lt;/code&gt; option doesn&amp;rsquo;t work the same on Mac OS (&lt;code&gt;man ps&lt;/code&gt; for details)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;strace&#34;&gt;strace&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: monitors interactions between processes, by highlighting what syscalls are being made&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;strace&lt;/code&gt; is awesome for understanding &lt;em&gt;exactly&lt;/em&gt; what your application is doing. If you have (just for example) a Python or Ruby app, then you should know that all the function calls it makes are actually abstractions provided by the language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most high-level languages are written in C, and so those abstracted functions will end up calling some internal C functions and those C functions will end up making OS level system calls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s these &amp;lsquo;system calls&amp;rsquo; that you&amp;rsquo;ll end up tracing/tracking with &lt;code&gt;strace&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-strace.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-strace.jpg&#34; alt=&#34;shell strace&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This utility isn&amp;rsquo;t available on Mac OS, so you&amp;rsquo;ll need Linux:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With Ubuntu:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install strace&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With CentOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;yum install strace&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Mac OS has &lt;code&gt;dtrace&lt;/code&gt; but it does use quite different commands from &lt;code&gt;strace&lt;/code&gt;&lt;br&gt;&#xA;Although I have seen articles online that help translate&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You can run &lt;code&gt;strace&lt;/code&gt; against a new process, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace ls -l&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But you can also &lt;em&gt;attach&lt;/em&gt; strace to an already running process! This is great for debugging an application that&amp;rsquo;s misbehaving out in the wild. You would do that like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace -p &amp;lt;process_id&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s consider a simple example where we want to see what the shell command &lt;code&gt;ls -l&lt;/code&gt; is actually doing. First let&amp;rsquo;s trace it to get an idea of the output you&amp;rsquo;ll see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace ls -l&#xA;&#xA;execve(&amp;quot;/bin/ls&amp;quot;, [&amp;quot;ls&amp;quot;, &amp;quot;-l&amp;quot;], [/* 23 vars */]) = 0&#xA;brk(0)                                  = 0x109a000&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f946a000&#xA;access(&amp;quot;/etc/ld.so.preload&amp;quot;, R_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/etc/ld.so.cache&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=32096, ...}) = 0&#xA;mmap(NULL, 32096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f22f9462000&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libselinux.so.1&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0\0[\0\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=134296, ...}) = 0&#xA;mmap(NULL, 2238192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f9027000&#xA;mprotect(0x7f22f9047000, 2093056, PROT_NONE) = 0&#xA;mmap(0x7f22f9246000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;mmap(0x7f22f9248000, 5872, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS...&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libacl.so.1&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0`\34\0\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=31168, ...}) = 0&#xA;mmap(NULL, 2126336, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f8e1f000&#xA;mprotect(0x7f22f8e26000, 2093056, PROT_NONE) = 0&#xA;mmap(0x7f22f9025000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libc.so.6&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0P \2\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f9461000&#xA;mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f8a5a000&#xA;mprotect(0x7f22f8c14000, 2097152, PROT_NONE) = 0&#xA;mmap(0x7f22f8e14000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;mmap(0x7f22f8e1a000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS...&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libpcre.so.3&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0\260\27\0\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=252032, ...}) = 0&#xA;mmap(NULL, 2347200, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f881c000&#xA;mprotect(0x7f22f8859000, 2093056, PROT_NONE) = 0&#xA;mmap(0x7f22f8a58000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libdl.so.2&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0\320\16\0\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=14664, ...}) = 0&#xA;mmap(NULL, 2109744, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f8618000&#xA;mprotect(0x7f22f861b000, 2093056, PROT_NONE) = 0&#xA;mmap(0x7f22f881a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;close(3)                                = 0&#xA;access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK)      = -1 ENOENT (No such file or directory)&#xA;open(&amp;quot;/lib/x86_64-linux-gnu/libattr.so.1&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;read(3, &amp;quot;\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0&amp;gt;\0\1\0\0\0\300\20\0\0\0\0\0\0&amp;quot;..., 832) = 832&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=18624, ...}) = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f9460000&#xA;mmap(NULL, 2113760, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f22f8413000&#xA;mprotect(0x7f22f8417000, 2093056, PROT_NONE) = 0&#xA;mmap(0x7f22f8616000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE...&#xA;close(3)                                = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f945f000&#xA;mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f945d000&#xA;arch_prctl(ARCH_SET_FS, 0x7f22f945d840) = 0&#xA;mprotect(0x7f22f8e14000, 16384, PROT_READ) = 0&#xA;mprotect(0x7f22f8616000, 4096, PROT_READ) = 0&#xA;mprotect(0x7f22f881a000, 4096, PROT_READ) = 0&#xA;mprotect(0x7f22f8a58000, 4096, PROT_READ) = 0&#xA;mprotect(0x7f22f9025000, 4096, PROT_READ) = 0&#xA;mprotect(0x7f22f9246000, 4096, PROT_READ) = 0&#xA;mprotect(0x619000, 4096, PROT_READ)     = 0&#xA;mprotect(0x7f22f946c000, 4096, PROT_READ) = 0&#xA;munmap(0x7f22f9462000, 32096)           = 0&#xA;statfs(&amp;quot;/sys/fs/selinux&amp;quot;, 0x7ffca795ea30) = -1 ENOENT (No such file or directory)&#xA;statfs(&amp;quot;/selinux&amp;quot;, 0x7ffca795ea30)      = -1 ENOENT (No such file or directory)&#xA;brk(0)                                  = 0x109a000&#xA;brk(0x10bb000)                          = 0x10bb000&#xA;open(&amp;quot;/proc/filesystems&amp;quot;, O_RDONLY)     = 3&#xA;fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f9469000&#xA;read(3, &amp;quot;nodev\tsysfs\nnodev\trootfs\nnodev\tr&amp;quot;..., 1024) = 384&#xA;read(3, &amp;quot;&amp;quot;, 1024)                       = 0&#xA;close(3)                                = 0&#xA;munmap(0x7f22f9469000, 4096)            = 0&#xA;open(&amp;quot;/usr/lib/locale/locale-archive&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=1607664, ...}) = 0&#xA;mmap(NULL, 1607664, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f22f92d4000&#xA;close(3)                                = 0&#xA;ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost...&#xA;ioctl(1, TIOCGWINSZ, {ws_row=53, ws_col=172, ws_xpixel=1895, ws_ypixel=1171}) = 0&#xA;open(&amp;quot;/usr/share/locale/locale.alias&amp;quot;, O_RDONLY|O_CLOEXEC) = 3&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=2570, ...}) = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f9469000&#xA;read(3, &amp;quot;# Locale name alias data base.\n#&amp;quot;..., 4096) = 2570&#xA;read(3, &amp;quot;&amp;quot;, 4096)                       = 0&#xA;close(3)                                = 0&#xA;munmap(0x7f22f9469000, 4096)            = 0&#xA;open(&amp;quot;/usr/share/locale/en_US.UTF-8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en_US.utf8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en_US/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en.UTF-8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en.utf8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US.UTF-8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US.utf8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en.UTF-8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en.utf8/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en/LC_TIME/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache&amp;quot;, O_RDONLY) = 3&#xA;fstat(3, {st_mode=S_IFREG|0644, st_size=26258, ...}) = 0&#xA;mmap(NULL, 26258, PROT_READ, MAP_SHARED, 3, 0) = 0x7f22f9463000&#xA;close(3)                                = 0&#xA;openat(AT_FDCWD, &amp;quot;.&amp;quot;, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3&#xA;getdents(3, /* 10 entries */, 32768)    = 296&#xA;getdents(3, /* 0 entries */, 32768)     = 0&#xA;close(3)                                = 0&#xA;open(&amp;quot;/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale/en/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US.UTF-8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US.utf8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en_US/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en.UTF-8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en.utf8/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;open(&amp;quot;/usr/share/locale-langpack/en/LC_MESSAGES/coreutils.mo&amp;quot;, O_RDONLY) = -1 ENOENT &#xA;fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0&#xA;mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f22f9462000&#xA;write(1, &amp;quot;total 0\n&amp;quot;, 8total 0&#xA;)                = 8&#xA;close(1)                                = 0&#xA;munmap(0x7f22f9462000, 4096)            = 0&#xA;close(2)                                = 0&#xA;exit_group(0)                           = ?&#xA;+++ exited with 0 +++&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK&amp;hellip; so that&amp;rsquo;s a lot of noise. So let&amp;rsquo;s see if we can&amp;rsquo;t quieten it down a bit by using the count flag &lt;code&gt;-c&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace -c ls -l&#xA;&#xA;total 0&#xA;% time     seconds  usecs/call     calls    errors syscall&#xA;------ ----------- ----------- --------- --------- ----------------&#xA;  0.00    0.000000           0        10           read&#xA;  0.00    0.000000           0         1           write&#xA;  0.00    0.000000           0        35        24 open&#xA;  0.00    0.000000           0        14           close&#xA;  0.00    0.000000           0        12           fstat&#xA;  0.00    0.000000           0        25           mmap&#xA;  0.00    0.000000           0        14           mprotect&#xA;  0.00    0.000000           0         4           munmap&#xA;  0.00    0.000000           0         3           brk&#xA;  0.00    0.000000           0         2           ioctl&#xA;  0.00    0.000000           0         8         8 access&#xA;  0.00    0.000000           0         1           execve&#xA;  0.00    0.000000           0         2           getdents&#xA;  0.00    0.000000           0         2         2 statfs&#xA;  0.00    0.000000           0         1           arch_prctl&#xA;  0.00    0.000000           0         1           openat&#xA;------ ----------- ----------- --------- --------- ----------------&#xA;100.00    0.000000                   135        34 total&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now &lt;em&gt;that&amp;rsquo;s&lt;/em&gt; better. We get a good overview of what syscalls have been made by the &lt;code&gt;ls&lt;/code&gt; program, how many times and the overall time involved for each type of function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But as you can see, when tracing a program that only lists the files in a directory (i.e. &lt;code&gt;ls -l&lt;/code&gt;), you&amp;rsquo;re not going to see much in the way of &amp;lsquo;time&amp;rsquo;. So let&amp;rsquo;s use &lt;code&gt;lsof&lt;/code&gt; (will read more about this later), which can take a few seconds to run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace -c lsof&#xA;&#xA;% time     seconds  usecs/call     calls    errors syscall&#xA;------ ----------- ----------- --------- --------- ----------------&#xA; 66.25    0.018456           7      2479           write&#xA;  7.11    0.001980           1      1405           read&#xA;  4.44    0.001237           1      2067        12 stat&#xA;  3.77    0.001051           1      2074      1021 close&#xA;  3.61    0.001007           4       244           alarm&#xA;  3.08    0.000857           2       543           munmap&#xA;  2.18    0.000608           2       244           rt_sigaction&#xA;  2.06    0.000575         575         1           wait4&#xA;  1.72    0.000479           1       554           fstat&#xA;  1.70    0.000474           1       875        57 readlink&#xA;  1.30    0.000363           0       834        20 open&#xA;  0.84    0.000235           0       507           lstat&#xA;  0.83    0.000230           0       568           mmap&#xA;  0.60    0.000167           1       222           openat&#xA;  0.42    0.000116           8        14           recvmsg&#xA;  0.09    0.000024           0       444           getdents&#xA;  0.00    0.000000           0         2           poll&#xA;  0.00    0.000000           0        17           lseek&#xA;  0.00    0.000000           0        18           mprotect&#xA;  0.00    0.000000           0        13           brk&#xA;  0.00    0.000000           0         1           ioctl&#xA;  0.00    0.000000           0        11        11 access&#xA;  0.00    0.000000           0         2           pipe&#xA;  0.00    0.000000           0         1           getpid&#xA;  0.00    0.000000           0        14           socket&#xA;  0.00    0.000000           0         7         6 connect&#xA;  0.00    0.000000           0         8           sendto&#xA;  0.00    0.000000           0         1           recvfrom&#xA;  0.00    0.000000           0         7           setsockopt&#xA;  0.00    0.000000           0         1           clone&#xA;  0.00    0.000000           0         1           execve&#xA;  0.00    0.000000           0         5           uname&#xA;  0.00    0.000000           0         1           umask&#xA;  0.00    0.000000           0         1           getrlimit&#xA;  0.00    0.000000           0         1           getuid&#xA;  0.00    0.000000           0         1           getgid&#xA;  0.00    0.000000           0         1           geteuid&#xA;  0.00    0.000000           0         1           getegid&#xA;  0.00    0.000000           0         1           arch_prctl&#xA;------ ----------- ----------- --------- --------- ----------------&#xA;100.00    0.027859                 13191      1127 total&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK &lt;em&gt;that&lt;/em&gt; output is a bit more practical, as we can see that the &lt;code&gt;write&lt;/code&gt; syscall took approximately 66% of the overall time of the program to run. If this was your own application you might consider that an issue worth delving into more deeply.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to get a rough idea for what some of these system calls mean, then use the below quick guide (otherwise &lt;a href=&#34;https://www.google.co.uk/search?q=close&amp;amp;sitesearch=man7.org/linux/man-pages&#34; target=&#34;_blank&#34;&gt;Google is your friend&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;table&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Syscall&lt;/th&gt;&#xA;      &lt;th&gt;What it does?&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;read&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;read bytes from a file descriptor (file, socket)&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;write&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;write bytes from a file descriptor (file, socket)&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;open&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;open a file (returns a file descriptor)&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;close&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;close a file descriptor&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;fork&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;create a new process (current process is forked)&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;exec&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;execute a new program&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;connect&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;connect to a network host&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;accept&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;accept a network connection&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;stat&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;read file statistics&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;ioctl&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;set I/O properties, or other miscellaneous functions&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;mmap&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;map a file to the process memory address space&lt;/td&gt;&lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&#xA;        &lt;tt&gt;brk&lt;/tt&gt;&lt;/td&gt;&#xA;      &lt;td&gt;extend the heap pointer&lt;/td&gt;&lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;p&gt;For debugging with &lt;code&gt;strace&lt;/code&gt; I&amp;rsquo;d suggest using the &lt;code&gt;-c&lt;/code&gt; flag first so you get a feel for any particular system calls that stand out as being quite odd.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe you notice a lot of network connections being opened and your app is showing signs of struggling with throughput. So you might then use &lt;code&gt;strace&lt;/code&gt; without the &lt;code&gt;-c&lt;/code&gt; so you could delve into the specific details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re debugging on a remote server that&amp;rsquo;s running a web app, you might attach strace to the running server process and then start manually &lt;code&gt;curl&lt;/code&gt;ing endpoints to see what sort of reaction the server has.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe you only want to look out for certain types of system calls. In that case you can utilise filters (&lt;code&gt;-e&lt;/code&gt;). In the following example we&amp;rsquo;re only interested in the &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;connect&lt;/code&gt; and &lt;code&gt;access&lt;/code&gt; syscalls:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace -e trace=open,connect,access lsof&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also use &lt;code&gt;!&lt;/code&gt; to negate the filter (see &lt;code&gt;man strace&lt;/code&gt; for more details)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you try to use &lt;code&gt;grep&lt;/code&gt; instead of &lt;code&gt;-e&lt;/code&gt; then you&amp;rsquo;ll need to ensure you redirect stderr to stdout or you wont see any output as strace sends to stderr by default; meaning you&amp;rsquo;d need to execute something like &lt;code&gt;strace uptime 2&amp;gt;&amp;amp;1 | grep open&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You might also find that using the &lt;code&gt;-t&lt;/code&gt; flag useful for tracking &lt;em&gt;when&lt;/em&gt; the call was made:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;strace -t -e trace=access lsof&#xA;&#xA;19:01:00 access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK) = -1 ENOENT (No such file or directory)&#xA;19:01:00 access(&amp;quot;/etc/ld.so.preload&amp;quot;, R_OK) = -1 ENOENT (No such file or directory)&#xA;19:01:00 access(&amp;quot;/etc/ld.so.nohwcap&amp;quot;, F_OK) = -1 ENOENT (No such file or directory)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see &lt;code&gt;strace&lt;/code&gt; is a really useful tool when the time comes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;and the time &lt;em&gt;will&lt;/em&gt; come.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By the way, you should be careful with backgrounded processes. If you attach to a backgrounded process running in the same shell instance as your &lt;code&gt;strace&lt;/code&gt; execution, then you&amp;rsquo;ll be locked up.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although &lt;code&gt;strace&lt;/code&gt; is amazing, you might also want to read &lt;a href=&#34;http://www.brendangregg.com/blog/2014-05-11/strace-wow-much-syscall.html&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt; that discusses the oft-ignored performance overhead of using it in production&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;lsof&#34;&gt;lsof&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: lists open files&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-lsof.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-lsof.jpg&#34; alt=&#34;shell lsof&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we actually saw this used earlier when looking at &lt;code&gt;strace&lt;/code&gt;. It will display all open files, and any one who knows a bit about operating systems will realise that an open file could in fact be any of the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a regular file&lt;/li&gt;&#xA;&lt;li&gt;a directory&lt;/li&gt;&#xA;&lt;li&gt;a block special file&lt;/li&gt;&#xA;&lt;li&gt;a character special file&lt;/li&gt;&#xA;&lt;li&gt;an executing text reference&lt;/li&gt;&#xA;&lt;li&gt;a library&lt;/li&gt;&#xA;&lt;li&gt;a stream or a network file (Internet socket, NFS file or UNIX domain socket)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This means that &lt;code&gt;lsof&lt;/code&gt; isn&amp;rsquo;t as pointless as you may have initially thought. Considering nearly everything in a *nix environment &amp;lsquo;is a file&amp;rsquo; (including network sockets).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to use this command, let&amp;rsquo;s see some simple examples:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;lsof -u &amp;lt;user&amp;gt;&lt;/code&gt;: filter results by specific user&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;lsof -i TCP:22 -n&lt;/code&gt;: lists all running processes on port 22 (ssh)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;lsof -i 4&lt;/code&gt;: display only IPv4 network files&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For example, with that last command (show the IPv4 network files) running on my Mac OS laptop, I see all sorts of processes such as: Slack, Chrome, Spotify etc. Lots of interesting information&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is one of those tools that might not get used very often, but when the right problem occurs it can be a real time saver being able to see what files your machine has open.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;netstat&#34;&gt;netstat&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: monitors network traffic&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;netstat&lt;/code&gt; (network statistics) command is useful because it allows us to see network connections for TCP (both incoming and outgoing), routing tables, and a number of network interface and network protocol statistics.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This gives us an insight into what network communications are going on and whether certain services are talking to the right endpoints, how often and whether their connections are being established or terminated correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-netstat.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-netstat.jpg&#34; alt=&#34;shell netstat&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some useful examples you can try out:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -a&lt;/code&gt;: show both listening and non-listening sockets (for TCP this means established connections)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -l&lt;/code&gt;: show just listening sockets&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -lt&lt;/code&gt;: show just tcp sockets&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -lu&lt;/code&gt;: show just udp sockets&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -aep&lt;/code&gt;: extend to show the user and also the pids&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -aepn&lt;/code&gt;: don&amp;rsquo;t translate host names (e.g. show ip instead)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -aepT&lt;/code&gt;: show host name but don&amp;rsquo;t truncate it&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -ax&lt;/code&gt;: show just UNIX domain sockets&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -st&lt;/code&gt;: shows summary of connections (useful for identifying TCP connection issues)&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -lc &amp;lt;n_seconds&amp;gt;&lt;/code&gt;: show listening sockets whilst continously refreshing every n seconds&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;netstat -atepn&lt;/code&gt;: nice &amp;lsquo;general&amp;rsquo; all-rounder (see below for example output)&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;  Active Internet connections (servers and established)&#xA;  Proto Recv-Q Send-Q Local Address               Foreign Address             &#xA;  tcp        0      0 0.0.0.0:8126                0.0.0.0:*                   &#xA;  tcp        0      0 0.0.0.0:8080                0.0.0.0:*                   &#xA;  tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   &#xA;  tcp        0      0 127.0.0.1:24220             0.0.0.0:*                   &#xA;  tcp        0      0 10.6.4.51:57228             10.6.31.176:6379            &#xA;  tcp        0      0 10.6.4.51:57224             10.6.31.176:6379            &#xA;  tcp        0      0 10.6.4.51:8080              10.6.8.80:48205             &#xA;  tcp        0      0 10.6.4.51:57231             10.6.31.176:6379            &#xA;  tcp        0      0 10.6.4.51:57225             10.6.31.176:6379            &#xA;  tcp        0      0 10.6.4.51:8080              10.6.6.76:51764             &#xA;  tcp       53      0 10.6.4.51:56870             54.231.142.40:443           &#xA;  tcp        1      0 127.0.0.1:34704             127.0.0.1:8080              &#xA;&#xA;  State       User       Inode      PID/Program name   &#xA;  LISTEN      0          8934       1071/statsd         &#xA;  LISTEN      498        10087      1355/puma 2.14.0 (t &#xA;  LISTEN      0          8763       1196/sshd           &#xA;  LISTEN      497        9296       1307/ruby           &#xA;  ESTABLISHED 498        218757     1355/puma 2.14.0 (t &#xA;  ESTABLISHED 498        218743     1355/puma 2.14.0 (t &#xA;  ESTABLISHED 498        229190     1355/puma 2.14.0 (t &#xA;  ESTABLISHED 498        218766     1355/puma 2.14.0 (t &#xA;  ESTABLISHED 498        218747     1355/puma 2.14.0 (t &#xA;  ESTABLISHED 498        10111      1355/puma 2.14.0 (t &#xA;  ESTABLISHED 497        229141     1307/ruby           &#xA;  CLOSE_WAIT  48         226010     20286/httpd&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;netstat -r&lt;/code&gt;: shows routing table (see below for example output)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;  Kernel IP routing table&#xA;  Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface&#xA;  10.6.0.0        *               255.255.248.0   U         0 0          0 eth0&#xA;  link-local      *               255.255.0.0     U         0 0          0 eth0&#xA;  default         ip-xx-x-x-x.eu- 0.0.0.0         UG        0 0          0 eth0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Effectively, if you&amp;rsquo;ve any kind of network issues, then this tool can help you potentially identify where it&amp;rsquo;s coming from or going (or if it&amp;rsquo;s not coming from or going to the expected source/destination).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Update: an easy way to remember this (thanks Julia Evans - see &lt;a href=&#34;#16&#34;&gt;honorable mentions&lt;/a&gt; is &amp;ldquo;tuna please&amp;rdquo; &lt;code&gt;netstat -tunapl&lt;/code&gt;). You can use &lt;code&gt;lsof -i -P&lt;/code&gt; on Mac OS&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;ifconfig&#34;&gt;ifconfig&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: configure or review your network interfaces&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ifconfig&lt;/code&gt; command is used to configure or review your network interfaces and can help you identify if there is a problem with your network (such as no Ethernet or WiFi or maybe your connections are misbehaving due to misconfiguration).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because networking is a big topic, and I&amp;rsquo;m not very good at it, I&amp;rsquo;ll refer you to the following article which provides a breakdown of typical data ouput: &lt;a href=&#34;http://www.aboutlinux.info/2006/11/ifconfig-dissected-and-demystified.html&#34; target=&#34;_blank&#34;&gt;www.aboutlinux.info/2006/11/ifconfig-dissected-and-demystified&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-ifconfig.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-ifconfig.jpg&#34; alt=&#34;shell ifconfig&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to configure a network interface, then running the &lt;code&gt;ifconfig&lt;/code&gt; command without any arguments will display all existing network interfaces:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;eth0      Link encap:Ethernet  HWaddr 0A:05:1E:A5:6F:FF  &#xA;          inet addr:10.6.4.51  Bcast:10.6.7.255  Mask:255.255.248.0&#xA;          inet6 addr: fe80::805:1eff:fea5:6fff/64 Scope:Link&#xA;          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1&#xA;          RX packets:8776319 errors:0 dropped:0 overruns:0 frame:0&#xA;          TX packets:4212889 errors:0 dropped:0 overruns:0 carrier:0&#xA;          collisions:0 txqueuelen:1000 &#xA;          RX bytes:10239965628 (9.5 GiB)  TX bytes:10967533931 (10.2 GiB)&#xA;          Interrupt:155 &#xA;&#xA;lo        Link encap:Local Loopback  &#xA;          inet addr:127.0.0.1  Mask:255.0.0.0&#xA;          inet6 addr: ::1/128 Scope:Host&#xA;          UP LOOPBACK RUNNING  MTU:65536  Metric:1&#xA;          RX packets:341240 errors:0 dropped:0 overruns:0 frame:0&#xA;          TX packets:341240 errors:0 dropped:0 overruns:0 carrier:0&#xA;          collisions:0 txqueuelen:0 &#xA;          RX bytes:31612016 (30.1 MiB)  TX bytes:31612016 (30.1 MiB)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see above that we have a single Ethernet card (&lt;code&gt;eth0&lt;/code&gt;) and a loop back interface (&lt;code&gt;lo&lt;/code&gt;)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In newer Linux OS&amp;rsquo; &lt;code&gt;eth&amp;lt;n&amp;gt;&lt;/code&gt; is replaced by &lt;code&gt;p2p&amp;lt;n&amp;gt;&lt;/code&gt;&lt;br&gt;&#xA;And on the Mac OS it becomes &lt;code&gt;en&amp;lt;n&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you want to find out which interface your WiFi is associated with, then you can use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ networksetup -listallhardwareports&#xA;&#xA;Hardware Port: Wi-Fi&#xA;Device: en0&#xA;Ethernet Address: 38:f9:d3:9e:9f:2b&#xA;&#xA;Hardware Port: Bluetooth PAN&#xA;Device: en6&#xA;Ethernet Address: 38:f9:d3:95:5c:fc&#xA;&#xA;Hardware Port: Thunderbolt 1&#xA;Device: en1&#xA;Ethernet Address: 5a:00:5c:52:d9:01&#xA;&#xA;Hardware Port: Thunderbolt 2&#xA;Device: en2&#xA;Ethernet Address: 5a:00:5c:52:d9:00&#xA;&#xA;Hardware Port: Thunderbolt 3&#xA;Device: en3&#xA;Ethernet Address: 5a:00:5c:52:d9:05&#xA;&#xA;Hardware Port: Thunderbolt 4&#xA;Device: en4&#xA;Ethernet Address: 5a:00:5c:52:d9:04&#xA;&#xA;Hardware Port: Thunderbolt Bridge&#xA;Device: bridge0&#xA;Ethernet Address: 5a:00:5c:52:d9:01&#xA;&#xA;VLAN Configurations&#xA;===================&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For more information on Network ips and how they&amp;rsquo;re created (i.e. CIDRs), then you might be interested in &lt;a href=&#34;https://gist.github.com/Integralist/cff468ba808fbca09602&#34; target=&#34;_blank&#34;&gt;this quick gist&lt;/a&gt; (but it&amp;rsquo;s only basic information, so you might have better luck with your own Googling)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;iftop&#34;&gt;iftop&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: monitors network traffic and displays table of bandwidth usage&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;iftop&lt;/code&gt; command is useful for identifying things like &amp;ldquo;why is our connection so slow?&amp;rdquo;. It&amp;rsquo;s equivalent to a tool like &lt;code&gt;top&lt;/code&gt; when understanding CPU usage.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The command listens to network traffic on a named interface and displays a table of current bandwidth usage by pairs of hosts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-iftop.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-iftop.jpg&#34; alt=&#34;shell iftop&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This utility isn&amp;rsquo;t available by default on any OS, so with Mac OS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install iftop&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With Ubuntu:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install iftop&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With CentOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;yum install wget libpcap -y&#xA;wget http://pkgs.repoforge.org/iftop/iftop-0.17-1.el6.rf.x86_64.rpm&#xA;rpm -ivh iftop-0.17-1.el6.rf.x86_64.rpm&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Below is a simple command to get you started:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sudo iftop -P -i en1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;use &lt;code&gt;ifconfig&lt;/code&gt; to find the interface you&amp;rsquo;re interested in&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I personally find the standard output useful (as per image above), but if you press &lt;code&gt;?&lt;/code&gt; while the program is running you&amp;rsquo;ll see lots of additional options you can try:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Host display:                          General:&#xA; n - toggle DNS host resolution         P - pause display&#xA; s - toggle show source host            h - toggle this help display&#xA; d - toggle show destination host       b - toggle bar graph display&#xA; t - cycle line display mode            B - cycle bar graph average&#xA;                                        T - toggle cumulative line totals&#xA;Port display:                           j/k - scroll display&#xA; N - toggle service resolution          f - edit filter code&#xA; S - toggle show source port            l - set screen filter&#xA; D - toggle show destination port       L - lin/log scales&#xA; p - toggle port display                ! - shell command&#xA;                                        q - quit&#xA;Sorting:&#xA; 1/2/3 - sort by 1st/2nd/3rd column&#xA; &amp;lt; - sort by source name&#xA; &amp;gt; - sort by dest name&#xA; o - freeze current order&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;iptraf&#34;&gt;iptraf&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: monitors network traffic (more visual than &lt;code&gt;netstat&lt;/code&gt;, but not as detailed)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-iptraf.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-iptraf.jpg&#34; alt=&#34;shell iptraf&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This utility isn&amp;rsquo;t available on Mac OS, so you&amp;rsquo;ll need Linux:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With Ubuntu:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install iptraf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With CentOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;yum install iptraf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Because &lt;code&gt;iptraf&lt;/code&gt; requires a lot of user interaction to get into different sections of the tool, I&amp;rsquo;ll have to just leave it up to you to explore.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But you&amp;rsquo;ll see options like &lt;code&gt;IP traffic monitor&lt;/code&gt;, which can be useful viewing. Personally I don&amp;rsquo;t find &lt;code&gt;iptraf&lt;/code&gt; as useful as tools such as &lt;code&gt;iftop&lt;/code&gt;. But it&amp;rsquo;s here for you nonetheless.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tcpdump&#34;&gt;tcpdump&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: network packet sniffer&lt;/p&gt;&#xA;&#xA;&lt;p&gt;tcpdump is a powerful and widely used command-line package analyzer, which is used to capture or filter TCP/IP packets received or transferred over a network on a specific interface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can save the output of this program into a &lt;code&gt;pcap&lt;/code&gt; file format, that can then be viewed by either tcpdump itself or via an open source GUI based tool such as &lt;a href=&#34;#13&#34;&gt;Wireshark&lt;/a&gt; that reads pcap format files and visualises the data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-tcpdump.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-tcpdump.jpg&#34; alt=&#34;shell tcpdump&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following are some examples to help you understand how to execute &lt;code&gt;tcpdump&lt;/code&gt;, but be aware that on some hosts you might need to run it with &lt;code&gt;sudo&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -D&lt;/code&gt;: show available network interfaces&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 -c 5&lt;/code&gt;: capture n packets from specific network interface&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 -c 5 -w 0001.pcap&lt;/code&gt;: send output to pcap file&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -r 0001.pcap&lt;/code&gt;: read back out the pcap file content for later analysis&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -n -i eth0 -c 1&lt;/code&gt;: converts dns hostnames into ip addresses instead&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -n -i eth0 -c 10 tcp&lt;/code&gt;: capture only tcp packets&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -n -i eth0 -c 10 port 22 and port 80&lt;/code&gt;: capture packets from specific ports&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 src &amp;lt;ip&amp;gt;&lt;/code&gt;: capture packets from a specific source ip&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 dst &amp;lt;ip&amp;gt;&lt;/code&gt;: capture packets for a specific destination ip&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 src port 80 or dst port 80&lt;/code&gt;: filter all HTTP traffic to or from port 80&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -i eth0 -s 0&lt;/code&gt;: include contents of each packet (not just the packet header)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump -vvv -s 0 -l -n port 53 -XX&lt;/code&gt;: watch all DNS traffic (which happens on port 53)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If you run tcpdump on a remote server, you&amp;rsquo;ll want to use the &lt;code&gt;-w&lt;/code&gt; flag to record the data into a pcap file, this is so you can scp the file back to your local machine for later aggregation/analysis with either tcpdump itself (&lt;code&gt;-r&lt;/code&gt;) or by importing the pcap file into another tool such as &lt;a href=&#34;#13&#34;&gt;&lt;code&gt;wireshark&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;#14&#34;&gt;&lt;code&gt;tshark&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The output of the program may look a little confusing but there is consistent structure you can look out for:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;date_time&amp;gt; &amp;lt;protocol&amp;gt; &amp;lt;src&amp;gt; &amp;gt; &amp;lt;dest&amp;gt;: Flags[&amp;lt;type&amp;gt;] &amp;lt;data&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;&amp;gt;&lt;/code&gt; always sits between &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;dest&lt;/code&gt; and indicates the direction of the request&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;flags&#34;&gt;Flags&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Flags aren&amp;rsquo;t always present, depending on the network transfer that has been recorded, but when it is you&amp;rsquo;ll usually see one of the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;[U] URG&lt;/code&gt;: used to identify incoming data as &amp;lsquo;urgent&amp;rsquo;. Such incoming segments do not have to wait until the previous segments are consumed by the receiving end but are sent directly and processed immediately&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[A] ACK&lt;/code&gt;:  the receiver will send an ACK that equals the senders sequence number&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[P] PSH&lt;/code&gt;: push exists to ensure that the data is given the priority (used quite frequently at the beginning and end of a data transfer, affecting the way the data is handled at both ends)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[R] RST&lt;/code&gt;: used when a segment arrives that is not intended for the current connection (remote host rejects packet and resets connection)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[S] SYN&lt;/code&gt;: initially sent when establishing the classic 3-way handshake between two hosts (one sent by Host A and one sent back with ACK by Host B)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[F] FIN&lt;/code&gt;: used to tear down the virtual connections created using the previous flag (SYN)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4 id=&#34;data&#34;&gt;Data&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll typically see more information within the &amp;lsquo;data&amp;rsquo; output to indicate information about the packets being passed between hosts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One such example would be seeing &lt;code&gt;win&lt;/code&gt; specified. This is a sliding &amp;lsquo;window&amp;rsquo; that represents the size of the packets being sent back and forth.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also typically see an ACK (acknowledgement packet), and that it won&amp;rsquo;t be sent until the previous packet has been completely received (this is to help with consistency of specific sequence numbers and the ability to signify packets have been missed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;win&lt;/code&gt; is also used for flow control. An example of this is where one end of the communication is having trouble keeping up with the number of packets and so they modify the window buffer to be a smaller packet size to allow themselves to catch up with their processing of data.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;last-packet&#34;&gt;Last Packet?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Although nothing to do with tcpdump, it is worth understanding (for the sake of debugging) that the &lt;code&gt;FIN&lt;/code&gt; flag doesn&amp;rsquo;t necessarily indicate the last packet has just been sent. Here is an example to explain:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Host A receives what it believes to be the last data packet&lt;/li&gt;&#xA;&lt;li&gt;So Host A sends a &lt;code&gt;FIN&lt;/code&gt; to tell Host B it&amp;rsquo;s closing its connection, along with an &lt;code&gt;ACK&lt;/code&gt; to acknowledge Host B&amp;rsquo;s last data packet&lt;/li&gt;&#xA;&lt;li&gt;Host B sends an &lt;code&gt;ACK&lt;/code&gt; to acknowledge receipt of Host A&amp;rsquo;s &lt;code&gt;FIN&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Host B then sends its own &lt;code&gt;FIN&lt;/code&gt; and &lt;code&gt;ACK&lt;/code&gt; to close its connection down&lt;/li&gt;&#xA;&lt;li&gt;Host A sends a final &lt;code&gt;ACK&lt;/code&gt; to acknowledge Host B&amp;rsquo;s last communication was received&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;wireshark&#34;&gt;wireshark&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: network packet sniffer and analyser (gui)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Wireshark is a network protocol analyzer.&lt;br&gt;&#xA;It lets you see what&amp;rsquo;s happening on your network at a microscopic level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-wireshark.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-wireshark.jpg&#34; alt=&#34;shell wireshark&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s not a lot I can say about Wireshark other than you really will need to know how certain network protocols (such as TCP) work in order to understand the output that&amp;rsquo;s being recorded.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The output will look very similar to what &lt;code&gt;tcpdump&lt;/code&gt; provides (depending on what network traffic you&amp;rsquo;re recording), and is a really useful tool for easier interrogation of pcap files created by &lt;code&gt;tcpdump&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This utility isn&amp;rsquo;t available by default on any OS, so with Mac OS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install wireshark --with-qt5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;sometimes the flags that are available change. So I would suggest running the command &lt;code&gt;brew cat wireshark&lt;/code&gt; first to see what&amp;rsquo;s available first.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;With Ubuntu:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install wireshark&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With CentOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;yum install wireshark&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I typically have only ever used Wireshark with pcap files I&amp;rsquo;ve created via &lt;code&gt;tcpdump&lt;/code&gt; so that&amp;rsquo;s what I&amp;rsquo;ll demonstrate here. There are two ways to open the pcap file in Wireshark.&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;p&gt;execute &lt;code&gt;wireshark&lt;/code&gt; from the terminal, which will open the gui, and from the gui interface select &amp;ldquo;Open Capture File&amp;rdquo;.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;execute &lt;code&gt;wireshark -r /path/to/pcap/file&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you just want to use Wireshark to monitor all network traffic, then execute &lt;code&gt;sudo wireshark -i &amp;lt;interface&amp;gt;&lt;/code&gt; (use &lt;code&gt;ifconfig&lt;/code&gt; or &lt;code&gt;sudo wireshark -D&lt;/code&gt; to see what interfaces are available). Once the gui is open it&amp;rsquo;ll have the specified interface pre-selected, so just double-click on it to start recording its traffic&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Every time there is (for example) a HTTP request, there might end up being 200 TCP packets recorded, which can be (as you could imagine) difficult to recognize and make sense of manually.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But this problem can be simplified within Wireshark by clicking on &amp;ldquo;Statistics&amp;rdquo; and then &amp;ldquo;Conversations&amp;rdquo;, where it will organize all these disparate packets into TCP sessions for you. Thus making analysing the data much easier.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we cover &amp;lsquo;filtering&amp;rsquo; more in the next section about tshark, but one simple search for a HTTP GET header in your recorded traffic is &lt;code&gt;frame contains &amp;quot;GET&amp;quot;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;docker&#34;&gt;Docker?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;One thing I did notice when trying to use this tool with Docker, was that you must run the container in privileged mode:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --privileged&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Otherwise you&amp;rsquo;ll see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;can&#39;t run /usr/sbin/dumpcap: Operation not permitted&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Apparently &lt;code&gt;--security-opt seccomp:unconfined&lt;/code&gt; is an alternative option.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following is taken and paraphrased from the Docker website:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Doing this will allow Docker to access all devices on the host as well as set some configuration to allow the container to nearly all the same access to the host as processes running outside the containers on the host.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;For more details, please refer to the &lt;a href=&#34;https://docs.docker.com/engine/reference/run/#/runtime-privilege-and-linux-capabilities&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tshark&#34;&gt;tshark&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: network packet sniffer and analyser (cli version of wireshark)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Tshark is a network protocol analyzer, but a terminal based one.&lt;br&gt;&#xA;It lets you see what&amp;rsquo;s happening on your network at a microscopic level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-tshark.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-tshark.jpg&#34; alt=&#34;shell tshark&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As mentioned above in the Wireshark section, to get access to &lt;code&gt;tshark&lt;/code&gt; on the Mac OS you need to install Wireshark. There are separate installs though for other OS&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With Ubuntu:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get install tshark&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With CentOS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;yum install tshark&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve only used tshark a few times and typically I find using the Wireshark gui better for interpretting tcpdump data (which has so far been one of my primary use cases; e.g. debugging traffic occuring on a remote server).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But the benefit of tshark, outside of those of us who love living inside the terminal, is the ability to automate analysis without the need for a gui. This means we can write scripts to process the data we&amp;rsquo;ve recorded and so becomes a very powerful tool.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Similar to Wireshark, if you want to read in a pcap file then you would use the &lt;code&gt;-r&lt;/code&gt; flag to point to its location on your file system:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;tshark -r /path/to/pcap/file&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Also you can just run tshark and have it monitor &lt;em&gt;all&lt;/em&gt; network traffic on your host machine or just a specific interface (using the &lt;code&gt;-i&lt;/code&gt; flag). There is also the &lt;code&gt;-D&lt;/code&gt; flag for having it show you all available interfaces you can listen on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The tshark command knows a lot more about what&amp;rsquo;s going on inside your TCP packets than tcpdump and so you have more options available to you in order to filter out the data you&amp;rsquo;re interested in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sudo tshark -i any \&#xA;            -R &#39;http.request.method == &amp;quot;GET&amp;quot;&#39; \&#xA;            -T fields \&#xA;            -e http.request.method -e http.request.uri -e ip.dst&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we&amp;rsquo;re &amp;lsquo;explicitly&amp;rsquo; listening on all interfaces for network traffic. We then filter out all packets except those which are a &lt;code&gt;HTTP GET&lt;/code&gt; request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now instead of just showing &lt;em&gt;all&lt;/em&gt; the data for the &lt;code&gt;HTTP GET&lt;/code&gt; requests that come through we use the &lt;code&gt;-T&lt;/code&gt; flag to indicate that we&amp;rsquo;re interested only in &amp;lsquo;fields&amp;rsquo; being displayed. We then can use the &lt;code&gt;-e&lt;/code&gt; flag to indicate which subset of &amp;lsquo;fields&amp;rsquo; we want to show.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case we&amp;rsquo;ve chosen to display the request method (i.e. &lt;code&gt;GET&lt;/code&gt;), the URI that was associated with the GET and the ip address associated with it.&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;filtering-example&#34;&gt;Filtering Example&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;One very real example I had recently was the need to inspect DNS traffic and to identify the TTL record values returned by the DNS resolutions happening on port 53.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I had used &lt;code&gt;tcpdump&lt;/code&gt; to record the relevant traffic:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;tcpdump -vvv -s 0 -l -n port 53 -XX -w dns-traffic.pcap&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I then was able to pass this into tshark to automate the extraction of useful data, all without having to consult the Wireshark gui (meaning I could do this within the same environment as the data was recorded in if I wanted to):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;tshark -r ~/dns-traffic.pcap -T fields -e dns.resp.ttl -e dns.resp.name&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;One useful trick some people aren&amp;rsquo;t aware of, is that if you are writing automation scripts with tshark but you&amp;rsquo;re unsure of how to access specific data fields, then just use Wireshark &lt;em&gt;temporarily&lt;/em&gt; to figure out the fields you need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if you open the pcap in wireshark, you can find the filter you need by selecting the data manually via the UI and then right-click&amp;rsquo;ing the relevant data field and selecting &amp;ldquo;Prepare a Filter &amp;gt; Selected&amp;rdquo;. This will generate the exact value you would assign to the tshark &lt;code&gt;-e&lt;/code&gt; flag.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the filtering system syntax is called BPF (Berkeley Packet Filter) and you can find &lt;a href=&#34;http://biot.com/capstats/bpf.html&#34; target=&#34;_blank&#34;&gt;documentation here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;telnet&#34;&gt;telnet&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: utility for communicating with another host&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Telnet is both a tool &lt;code&gt;telnet&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; a Network Protocol of the same name: Telnet. The &lt;code&gt;telnet&lt;/code&gt; program is used for interactive communication to a remote/external host on a given port. Once the connection to the remote host is established, an HTTP request can be sent to the host by typing it in the prompt.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/shell-telnet.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/shell-telnet.jpg&#34; alt=&#34;shell telnet&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Telnet&amp;rsquo;s usage nowadays is a little limited due to the massive success of protocols such as SSH, but it can be interesting to play around with (although I&amp;rsquo;ve never really had much of a &amp;lsquo;need&amp;rsquo; for it myself).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;one such tool that is more useful in this respect is &lt;a href=&#34;http://nc110.sourceforge.net/&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;netcat&lt;/code&gt;&lt;/a&gt; which reads and writes data across network connections, using the TCP or UDP protocols&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To use the command you type &lt;code&gt;telnet &amp;lt;host&amp;gt; &amp;lt;port&amp;gt;&lt;/code&gt;. Once &amp;lsquo;connected&amp;rsquo; to the host you need to provide a command to be executed, for example a &lt;code&gt;GET&lt;/code&gt; request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of making a GET request. First we must connect:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;telnet www.google.com 80&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We will get the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Trying 87.237.19.30...&#xA;Connected to www.google.com.&#xA;Escape character is &#39;^]&#39;.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From here we can provide our request:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;GET #q=cars HTTP/1.1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you need to press &lt;Enter&gt; twice to send the request&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;From here we get the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;HTTP/1.1 302 Found&#xA;Location: http://www.google.co.uk/?gws_rd=cr&amp;amp;ei=k7BjV-GbFOLOgAbd3JbADw#q=cars&#xA;Cache-Control: private&#xA;Content-Type: text/html; charset=UTF-8&#xA;P3P: CP=&amp;quot;This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info.&amp;quot;&#xA;Date: Fri, 17 Jun 2016 08:10:59 GMT&#xA;Server: gws&#xA;Content-Length: 268&#xA;X-XSS-Protection: 1; mode=block&#xA;X-Frame-Options: SAMEORIGIN&#xA;Set-Cookie: NID=80=123; expires=Sat, 17-Dec-2016 08:10:59 GMT; path=/; domain=.google.com; HttpOnly&#xA;&#xA;&amp;lt;HTML&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;meta http-equiv=&amp;quot;content-type&amp;quot; content=&amp;quot;text/html;charset=utf-8&amp;quot;&amp;gt;&#xA;&amp;lt;TITLE&amp;gt;302 Moved&amp;lt;/TITLE&amp;gt;&amp;lt;/HEAD&amp;gt;&amp;lt;BODY&amp;gt;&#xA;&amp;lt;H1&amp;gt;302 Moved&amp;lt;/H1&amp;gt;&#xA;The document has moved&#xA;&amp;lt;A HREF=&amp;quot;http://www.google.co.uk/?gws_rd=cr&amp;amp;amp;ei=k7BjV-GbFOLOgAbd3JbADw#q=cars&amp;quot;&amp;gt;here&amp;lt;/A&amp;gt;.&#xA;&amp;lt;/BODY&amp;gt;&amp;lt;/HTML&amp;gt;&#xA;Connection closed by foreign host.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we try a similar request with the BBC site, we&amp;rsquo;ll see we get a 404 not found:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ telnet www.bbc.co.uk 80&#xA;Trying 212.58.244.66...&#xA;Connected to www.bbc.net.uk.&#xA;Escape character is &#39;^]&#39;.&#xA;GET /news HTTP/1.1&#xA;&#xA;HTTP/1.1 404 Not Found&#xA;Content-Type: text/html&#xA;Date: Fri, 17 Jun 2016 08:13:29 GMT&#xA;Connection: Keep-Alive&#xA;Content-Length: 50591&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;honorable-mentions&#34;&gt;Honorable mentions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A few months after writing this article I stumbled across a similar (but much better) post from &lt;a href=&#34;https://twitter.com/b0rk&#34; target=&#34;_blank&#34;&gt;Julia Evans&lt;/a&gt;. I then realised she has written &lt;em&gt;lots&lt;/em&gt; of amazing posts, so you should &lt;a href=&#34;http://jvns.ca/&#34; target=&#34;_blank&#34;&gt;check them out&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some tools that she mentions that you should consider looking at:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;dstat: prints network/disk usage every second&lt;/li&gt;&#xA;&lt;li&gt;opensnoop: prints files being opened (but without strace perf concerns)&lt;/li&gt;&#xA;&lt;li&gt;netcat: connect, listen, tunnel with ease&lt;/li&gt;&#xA;&lt;li&gt;ngrep: provides grep functionality for the network&lt;/li&gt;&#xA;&lt;li&gt;perf: records a program on an interval for later analysis (also &lt;code&gt;perf top&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There you have it. A whirlwind run down of different terminal based debugging tools. The primary one&amp;rsquo;s (for me) being:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;strace&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tcpdump&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;wireshark&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tshark&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Obivously they all have their specialisms and unique features. I&amp;rsquo;ve not even scratched the surface of what they can do. If you know of anything really useful that I&amp;rsquo;ve missed, then let me know.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/terminal-utils/</guid>
      <link>https://www.integralist.co.uk/posts/terminal-utils/</link>
      <pubDate>Mon, 12 Sep 2016 00:00:00 +0000</pubDate>
      <title>Terminal Debugging Utilities</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What makes a good Pull Request?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The answer will depend on your team, and to a certain extent your organisation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Currently I work at BuzzFeed, and prior to that I worked at the BBC.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Both have a large number of engineers and teams, but due to different organisational structures they have differing opinions on what constitutes a good pull request format.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These opinions aren&amp;rsquo;t happening at the organisational level either, but are very much &amp;lsquo;team&amp;rsquo; specific. Teams work differently and so have different needs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below I discuss some ideas around what I&amp;rsquo;ve used in the past and what I&amp;rsquo;m using today and I&amp;rsquo;ll leave it as an exercise for the reader to determine what parts they decide to takeaway with them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why&#34;&gt;Why&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Probably the most important part of a pull request is understanding &lt;em&gt;why&lt;/em&gt; the change is needed in the first place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What exactly are you changing and is it even needed?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Are you solving a problem that promotes a real business requirement, or are you just adding a nice feature that doesn&amp;rsquo;t actually serve to improve the end user&amp;rsquo;s experience?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe the feature you&amp;rsquo;re adding is an internal improvement (e.g. refactor, dev tooling etc). That&amp;rsquo;s fine and I guess it comes down to how &lt;em&gt;your&lt;/em&gt; team prioritises its work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But taking a moment to stop and think about a new code change &lt;em&gt;before&lt;/em&gt; you start working on it, is an important step to take.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;size&#34;&gt;Size&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Pull requests should be small.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A large pull request that touches many different files across a project and has many different side effects, outcomes and responsibilities is extremely difficult to reason about from the perspective of the person reviewing the code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Small pull requests allow for quicker reviews and merging. It promotes an &lt;em&gt;iterative&lt;/em&gt; approach to implementing new features. It also helps to avoid conflicts when merging or rebasing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re also able to &amp;lsquo;fail fast&amp;rsquo; if our work priorities change and we need to switch gears or change direction altogether. We&amp;rsquo;re not trying to solve every problem all at once.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;process&#34;&gt;Process&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Pull requests should be opened almost immediately, to allow for team feedback and help in direction (depending on what you need).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me, this typically means making a single, small change and opening a pull request around it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once the pull request is open I utilise &amp;lsquo;labels&amp;rsquo; to signify the state of the pull request: &lt;code&gt;wip&lt;/code&gt; (work in progress), &lt;code&gt;rtr&lt;/code&gt; (ready to review), &lt;code&gt;rtm&lt;/code&gt; (ready to merge), &lt;code&gt;help&lt;/code&gt; (I actively &lt;em&gt;want&lt;/em&gt; engineers to chip in early and help me flesh out the design if they see something wrong).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I ensure I have a good pull request description that indicates &lt;em&gt;what&lt;/em&gt; the problem is that the pull request solves and &lt;em&gt;how&lt;/em&gt; it solves that problem. In markdown that would look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;**Problem**: ...&#xA;**Solution**: ...&#xA;&#xA;**Notes**: &#xA;&#xA;...&#xA;&#xA;**Todo**:&#xA;&#xA;- [ ] ...&#xA;- [ ] ...&#xA;- [ ] ...&#xA;&#xA;**Screen Shots**:&#xA;&#xA;![image alt text](http://some-image)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see above, this is a generic template. I like to have the problem and solution lines to be very concise and not to take up multiple lines.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;notes&amp;rsquo; section can be multiple lines so I keep it as an isolated section. This section can also include things like automated code linting or test suite coverage results.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;todo&amp;rsquo; section helps me to keep track of what tasks I have in order to complete this pull request, but it also helps other engineers to understand my thought process and see where I might be going &lt;em&gt;before&lt;/em&gt; I even get there (allowing the team to ask questions or make suggestions as per the &lt;code&gt;help&lt;/code&gt; label).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, the &amp;lsquo;screen shots&amp;rsquo; section is useful for those unfamiliar with the side effects of the change to be able to visually identify where the change appears or what it looks like. This isn&amp;rsquo;t always necessary, depending on the code change being made, but is useful for UI changes.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;communication&#34;&gt;Communication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to notify fellow team members that your pull request exists, in order for them to provide appropriate feedback.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can manually &lt;code&gt;@&amp;lt;username&amp;gt;&lt;/code&gt; people within a comment in the pull request, or you could create a team in GitHub and then &lt;code&gt;@&amp;lt;team-name&amp;gt;&lt;/code&gt; instead (helps especially for teams who like to rotate members across other teams within an organisation).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;merge-strategies&#34;&gt;Merge Strategies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve written in the past about different &amp;lsquo;&lt;a href=&#34;/posts/git-merge-strategies/&#34;&gt;git merge strategies&lt;/a&gt;&amp;rsquo;. My preferred way is to &lt;code&gt;git merge --squash&lt;/code&gt;, and luckily GitHub&amp;rsquo;s UI provides a &amp;lsquo;one click&amp;rsquo; way to squash merge a pull request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s what I suggest using for merging pull requests into &lt;code&gt;master&lt;/code&gt;, but you may have different requirements in your team/organisation, so pick whatever works best.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So this has been &lt;em&gt;my&lt;/em&gt; preferred approach to creating a good pull request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To recap, here is a top level look at the structure and concepts I suggest:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Small pull request&lt;/li&gt;&#xA;&lt;li&gt;Utilise labels to indicate status&lt;/li&gt;&#xA;&lt;li&gt;Consistent formatting:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Gif (optional)&lt;/li&gt;&#xA;&lt;li&gt;Problem/Solution&lt;/li&gt;&#xA;&lt;li&gt;Notes (optional)&lt;/li&gt;&#xA;&lt;li&gt;Todos (optional)&lt;/li&gt;&#xA;&lt;li&gt;Screen shot images (optional)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Agree a merge strategy for team consistency&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/github-pull-request-formatting/</guid>
      <link>https://www.integralist.co.uk/posts/github-pull-request-formatting/</link>
      <pubDate>Mon, 22 Aug 2016 00:00:00 +0000</pubDate>
      <title>GitHub Pull Request Formatting</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you first start learning algorithms (Binary Search, Quick Sort, Breadth-first Search etc), you&amp;rsquo;ll quickly realise that in order to take advantage of these algorithms, you need to know how fast they are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Otherwise, when presented with a programming problem in which you want to select an algorithm to use to solve that problem, how will you know which algorithm is more efficient?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way to know how fast an algorithm is, would be to use the &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Big_O&#34; target=&#34;_blank&#34;&gt;Big O&lt;/a&gt; notation.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understanding-big-o&#34;&gt;Understanding Big O&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Big O doesn&amp;rsquo;t tell you how fast in time (e.g. seconds) an algorithm is. Instead it informs you of the number of &lt;em&gt;operations&lt;/em&gt;, and how those operations will grow over time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although we&amp;rsquo;ll see how to calculate the speed of operations later on in this post, the primary benefit is to see &amp;lsquo;at a glance&amp;rsquo; the growth of operations as your data becomes larger.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;So the O in &amp;ldquo;Big O&amp;rdquo; means &amp;ldquo;Operation&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This means in order for you to really understand Big O you&amp;rsquo;re going to need to know some maths. Now, this is OK. I&amp;rsquo;m genuinely terrible at maths, but you&amp;rsquo;ll see as we go along that it&amp;rsquo;s not as complicated as you might think.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Effectively there are two math concepts we need to know:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Logarithms&lt;/li&gt;&#xA;&lt;li&gt;Factorials&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;You don&amp;rsquo;t even need to know that much about them. Only the bare minimum is required. So let&amp;rsquo;s make a start with Logarithms and then move onto Factorials afterwards. Once we understand those two concepts we can go back to Big O and start tying together some examples.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;logarithms&#34;&gt;Logarithms&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As I said, in order to understand Big O, you&amp;rsquo;ll need to understand how &lt;a href=&#34;https://en.wikipedia.org/wiki/Logarithm&#34; target=&#34;_blank&#34;&gt;Logarithms&lt;/a&gt; work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m terrible at Math, but luckily the awesome book &amp;ldquo;&lt;a href=&#34;https://www.manning.com/books/grokking-algorithms&#34; target=&#34;_blank&#34;&gt;Grokking Algorithms: An Illustrated Guide&lt;/a&gt;&amp;rdquo; (which I highly recommend) helped me at least understand the basics of Logarithms; enough so that I could then go on to understand Big O.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence the Logarithm notation looks something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Log n (х)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I had used a nice &lt;code&gt;𝑛&lt;/code&gt; icon instead of &lt;code&gt;n&lt;/code&gt; but on my phone I noticed it wasn&amp;rsquo;t showing :-/ so I had to change it to something that wasn&amp;rsquo;t a symbol.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;where the &lt;code&gt;n&lt;/code&gt; is what&amp;rsquo;s called the &amp;ldquo;base&amp;rdquo; and &lt;code&gt;х&lt;/code&gt; is the number you&amp;rsquo;re aiming for. But really what we&amp;rsquo;re interested in is the &lt;em&gt;result&lt;/em&gt; of this calculation.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;logarithm-example&#34;&gt;Logarithm Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Imagine we have the following Logarthim:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Log5(100)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this is effectively asking is:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;ldquo;how many times do I need to multiple 5 by itself in order to reach the number 100?&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s find out:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;5*5*5 = 125&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Looks like the result of our Logarithm would&amp;rsquo;ve been &lt;code&gt;3&lt;/code&gt;, because there were three &lt;code&gt;5&lt;/code&gt;&amp;rsquo;s used in order to get to a number that was equal or greater than &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this case the calculation wasn&amp;rsquo;t exactly equal. By that I mean we went &lt;em&gt;past&lt;/em&gt; &lt;code&gt;100&lt;/code&gt; and ended up at &lt;code&gt;125&lt;/code&gt;. But that&amp;rsquo;s the essence of how to understand what a Logarithm is asking and how to calculate the result.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we can see the calculation looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Log5(100) = 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;3&lt;/code&gt; is effectively the worst case number of steps involved when calculating that particular item.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The number &lt;code&gt;100&lt;/code&gt; in this case represents the number of items we have to execute our algorithm against. So if you were using an algorithm (such as a Binary Search; demonstrated later on below) and it was running over a collection of items, then the length of the items (in the above example Logarithm) would be &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll see how this is useful in measuring an algorithm&amp;rsquo;s &lt;em&gt;speed&lt;/em&gt; in a later section of this post. But for now let&amp;rsquo;s go and understand Factorials&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;factorials&#34;&gt;Factorials&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Factorials are one of those things that can come in handy for a number of reasons. But generally they&amp;rsquo;re really useful for identifying &amp;lsquo;variations&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have three letters:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;A&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;B&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;C&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;How many variations of these letters can you produce? So we have &lt;code&gt;A, B, C&lt;/code&gt; as one variation. &lt;code&gt;A, C, B&lt;/code&gt; would be another variation and then maybe &lt;code&gt;B, A, C&lt;/code&gt; would be another etc. But how do you calculate how many variations there are?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution is the factorial: &lt;code&gt;n!&lt;/code&gt; (where &lt;code&gt;n&lt;/code&gt; is the number of items you have).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in our example we had three items, so that would be written as &lt;code&gt;3!&lt;/code&gt; factorial.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Which really means:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;3*2*1 = 6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So that&amp;rsquo;s six variations you have for three items.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what if you have 10 items?&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10*9*8*7*6*5*4*3*2*1 = 3,628,800&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see that with a small number of items, the number of operations is massive. This is the total oposite of Logarithms which we looked at earlier (remember its growth of operations stayed consistently good when the collection grew).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although Factorials serve a useful purpose (the example given in the book &amp;ldquo;Grokking Algorithms&amp;rdquo; is one called &amp;lsquo;The Travelling Salesperson&amp;rsquo; - which is a problem that required calculating the quickest route the saleperson can take in order to visit n number of cities) they are probably the worst performing algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you see &lt;code&gt;n!&lt;/code&gt; you should be wary.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;back-to-big-o&#34;&gt;Back to Big O&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So now we understand how Logarithms and Factorials work we can come back to the Big O notation and understand that it&amp;rsquo;s really a simple visual wrapper around these different mathematical calculations.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(х)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above snippet, &lt;code&gt;х&lt;/code&gt; is a calculation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we were considering Logarithms, then it would look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(Log n (х))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we were considering Factorials, then it would look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(n!)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important noting that you&amp;rsquo;ll never see a specific calculation like &lt;code&gt;O(Log5(100))&lt;/code&gt; or &lt;code&gt;O(3!)&lt;/code&gt; in Big O. It&amp;rsquo;ll always be an abstract version like &lt;code&gt;O(Log n (х))&lt;/code&gt; or &lt;code&gt;O(n!)&lt;/code&gt; because Big O notation is a way of &lt;em&gt;talking&lt;/em&gt; to other people and having a &amp;lsquo;common language&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;ldquo;Hey Bob, I don&amp;rsquo;t think we should use the Simple Search algorithm because it&amp;rsquo;s &lt;code&gt;O(n)&lt;/code&gt;. We&amp;rsquo;d be much better off using a Binary Search, as that&amp;rsquo;s &lt;code&gt;O(Log n (х))&lt;/code&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;See how this gives us a common language. It&amp;rsquo;s similar to Design Patterns. Patterns can be implemented in a variety of different ways and yet we have common language for easily identifying code that follows a certain pattern (or when we think a particular pattern might be a good solution to a design problem, we have a common language for explaining the solution to someone else without needing to actually implement it first).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now my mention of &amp;lsquo;Simple Search&amp;rsquo; and &amp;lsquo;Binary Search&amp;rsquo; might not mean much to you, as you might not know how these algorithms work. So let&amp;rsquo;s look at these two algorithms next and then after that you&amp;rsquo;ll hopefully understand why Big O helps us understand the performance of these algorithms.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;simple-search&#34;&gt;Simple Search&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Simple Search is probably the simplest algorithm you&amp;rsquo;ll ever learn. You&amp;rsquo;ll see why in just a moment&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a collection of twelve items (and these items are numbers), which are sorted/in order. You are required to locate a particular item within that collection.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is the collection:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 20, 21]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The Simple Search approach is to loop over the collection one item at a time and check whether the current item matches the item you&amp;rsquo;re looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if the number you were looking for was &lt;code&gt;19&lt;/code&gt;, then that means you&amp;rsquo;ll first check &lt;code&gt;1&lt;/code&gt;, nope that&amp;rsquo;s not it. You&amp;rsquo;ll then check &lt;code&gt;3&lt;/code&gt;, nope that&amp;rsquo;s not it either&amp;hellip; and keep going until you reach the number you&amp;rsquo;re looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what does this algorithm look like in Big O?&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(n)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;what-does-big-o-tell-us&#34;&gt;What does Big O tell us?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Big O is telling us that this algorithm performs in &amp;lsquo;linear&amp;rsquo; time. This means the number of operations increase linearly with the number of items in the collection. So in the above example, the worst case number of operations will be 12. But if the collection length was 100 items, then the worst case number of operations would be 100.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in effect, the bigger the collection, the more &lt;em&gt;expensive&lt;/em&gt; this algorithm becomes. With a very small collection it&amp;rsquo;s fast because of its simplicity, but beyond a small collection it&amp;rsquo;s a poor performing choice of algorithm. This is what Big O is telling us here.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;binary-search&#34;&gt;Binary Search&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consider the same example as before, a collection of 12 items. The Binary Search algorithm is quite straight forward: you set the start and end indexes (usually zero for &amp;lsquo;start&amp;rsquo;, and the length of the collection for the &amp;lsquo;end&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now you locate the middle of the collection and check if the value you&amp;rsquo;re looking for either matches or is too low/high. If it matches, then hey great you&amp;rsquo;ve just reduced the number of operations by a large amount compared to the Simple Search.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the middle item (our &amp;lsquo;guess&amp;rsquo;) is lower than the actual item we&amp;rsquo;re looking for, then you reassign the value of &amp;lsquo;start&amp;rsquo; to be the middle index (the &amp;lsquo;end&amp;rsquo; stays set to the length of the collection). You&amp;rsquo;ve now reduced the sliding window of items by half.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Alternatively if the middle item was larger than the item we&amp;rsquo;re looking for, then you reassign the value &amp;lsquo;end&amp;rsquo; to be the middle index (the &amp;lsquo;start&amp;rsquo; stays set to zero). You&amp;rsquo;ve again reduced the sliding window of items by half.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here we &amp;lsquo;rinse/repeat&amp;rsquo; until the next &amp;lsquo;middle of the collection&amp;rsquo; selection is the item we&amp;rsquo;re looking for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a much more efficient search algorithm compared to Simple Search.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see what this looks like in Big O notation&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(Log n (х))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;what-does-big-o-tell-us-1&#34;&gt;What does Big O tell us?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Big O is telling us that this algorithm works in &amp;lsquo;log time&amp;rsquo;, which means the performance improves as the size of the collection increases! You can tell this &amp;lsquo;at a glance&amp;rsquo; with Big O syntax (especially as you now know how Logarithms work). This algorithm will perform well across a wide range of collection sizes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Big O in effect tells us how the operations &lt;em&gt;grow&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for this particular algorithm example, the worst case number of operations is &lt;code&gt;4&lt;/code&gt;. Take a look at our earlier explanation of Logarithms if you&amp;rsquo;re unsure why that is, but in a non-abstract sense this would look like: &lt;code&gt;O(Log2(12))&lt;/code&gt;. We&amp;rsquo;re dividing our collection in two (&lt;code&gt;Log2&lt;/code&gt;) for each operation (&lt;code&gt;(12)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is probably one of the best Big O&amp;rsquo;s you&amp;rsquo;ll come across as effectively the performance (and by that I mean the growth of the operations) stays consistently good as the size of the collection increases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you have a collection of 1000 items, then that would result in (worst case) &lt;code&gt;10&lt;/code&gt; operations required to locate the item you&amp;rsquo;re looking for:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;2*2*2*2*2*2*2*2*2*2 = 1024&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;How about a collection of a million items? That would be result in (worst case) &lt;code&gt;20&lt;/code&gt; (yes 20!) operations to find the item you were looking for amongst one million items. That&amp;rsquo;s incredible.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-travelling-salesperson&#34;&gt;The Travelling Salesperson&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not much to say here that we haven&amp;rsquo;t already mentioned earlier when talking about Factorials. This problem is about calculating the number of different routes someone can take in order to ensure they reach all the specified number of cities, and then working out which route was quickest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Big O notation this looks like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(n!)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;what-does-big-o-tell-us-2&#34;&gt;What does Big O tell us?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Big O is telling us this algorithm results in &amp;lsquo;factorial time&amp;rsquo;, and this is one of the worst performing algorithms known to mankind. Apparently it baffles the maths community, in that there isn&amp;rsquo;t actually a better algorithm to solve this problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So as we saw earlier, if there were ten cities to visit and we need to identify the quickest route to visit all ten cities, it would take us approximately &lt;code&gt;3,628,800&lt;/code&gt; operations to just calculate all the variations, before we could identify which one was quickest.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;calculating-operation-speed&#34;&gt;Calculating Operation Speed&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order to calculate the speed of an algorithm, we need to know the worst case number of operations. This is what Big O in effect gives us (whether it be linear time, log time or factorial time). So how do we calculate the speed based on the number of operations?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First we need to know how many operations can be executed within one second.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The answer to that question is ten operations:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1 second / 0.1 = 10 operations&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;your computer can handle more than 10 operations a second, but as we&amp;rsquo;ve said before, Big O is about worst case scenarios and so although not realistic; this number does give us a nice base line to work from&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We can then calculate the &lt;em&gt;time&lt;/em&gt; associated with a number of operations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine we have the following Big O:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(Log n (х))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If this was a collection of 16 items, then the non-abstract version would look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;O(Log2(16))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We know from our earlier discussions that this would result in a worst case result of &lt;code&gt;4&lt;/code&gt; operations to find the item we&amp;rsquo;re searching for.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Remember: &lt;code&gt;2x2x2x2 = 16&lt;/code&gt;&lt;br&gt;&#xA;That&amp;rsquo;s &lt;code&gt;4&lt;/code&gt; times we multipled &lt;code&gt;2&lt;/code&gt; by itself to reach &lt;code&gt;16&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;We also now know that a single operation takes &lt;code&gt;0.1&lt;/code&gt; of a second.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with this in mind we can calculate the speed of &lt;code&gt;O(Log2(16))&lt;/code&gt; as being: &lt;code&gt;0.4&lt;/code&gt; seconds&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0.1 * 4 operations = 0.4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we were using the Simple Search algorithm (which is &lt;code&gt;O(n)&lt;/code&gt;) on a collection of 16 items, then we know that this would take &lt;code&gt;1.6&lt;/code&gt; seconds to complete:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0.1 * 16 operations = 1.6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;arrays-vs-linked-lists&#34;&gt;Arrays vs Linked Lists&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s consider what Big O looks like for the Array and Linked List data structures.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An Array supports &amp;lsquo;index access&amp;rsquo;, meaning you can jump straight to an Array index. Whereas with Linked Lists you have to traverse the entire list in order to locate a specific item.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;another difference comes in memory management. Arrays require n number of memory &amp;lsquo;slots&amp;rsquo; to be next to each other, whereas Linked List memory can be sparse and spread out due to how it implements its internal chaining of nodes. This is why Arrays are typically considered to be &amp;lsquo;fixed size&amp;rsquo; and not easily expanded, because expansion of the Array&amp;rsquo;s size could potentially require an expensive movement of the Array to a new location in memory in order to faciliate a new index and yet still have memory slots side-by-side&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This suggests that Array lookups are &lt;code&gt;O(1)&lt;/code&gt;, known as &amp;lsquo;constant time&amp;rsquo; because the lookup growth stays the same no matter the length of the collection (i.e. it&amp;rsquo;s constant).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Linked List lookups on the other hand are &lt;code&gt;O(n)&lt;/code&gt;, which we already know is &amp;lsquo;linear time&amp;rsquo; (remember this is how the Simple Search algorithm performed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what about new data insertions? Well, with an Array you insert new items at the end of the Array, and because of its index access it would indicate &lt;code&gt;O(1)&lt;/code&gt;. But if you&amp;rsquo;re inserting an item into the middle of the Array, then this changes to &lt;code&gt;O(n)&lt;/code&gt; because of the internal implementation of Arrays in memory, it means you need to re-order all the following items, which is expensive (hence the side-effect of inserting into the middle is really more like linear time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Linked List insertions are generally &lt;code&gt;O(1)&lt;/code&gt; if inserting at the beginning or end of the list, but more like &lt;code&gt;O(n) + O(1)&lt;/code&gt; if inserting into the middle of the list because you have to traverse the list first and then insert your new item.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;selection-sort&#34;&gt;Selection Sort&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;selection sort&amp;rsquo; algorithm sorts an unordered list by looping over the list &lt;code&gt;n&lt;/code&gt; number of times, and for each loop it identifies either the smallest or largest element (which - smallest/largest - depends on how you&amp;rsquo;re hoping to sort your list: do you want ascending or descending order). But ultimately you&amp;rsquo;ll end up constructing a &lt;em&gt;new&lt;/em&gt; &amp;lsquo;ordered&amp;rsquo; list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically you loop a number of times to match the collection length. Then you loop the collection looking for smallest/largest item. Then you mutate the collection so it&amp;rsquo;s smaller by one.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This ends up being &lt;code&gt;O(n₂)&lt;/code&gt; (n to the power of 2, or &lt;code&gt;O(n * n)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although you&amp;rsquo;re looping over the collection multiple times, you are in fact looping over a slightly smaller collection each time. But it&amp;rsquo;s &lt;em&gt;still&lt;/em&gt; considered &lt;code&gt;O(n)&lt;/code&gt; for each time you loop over the collection because regardless of how many items are in there you treat it as abstract&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So if your collection is 10 items long, then it would calculate as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10 * 10 (i.e. n₂ meaning: 10 to the power of 2) = 100 operations&#xA;0.1 * 100 = 10 seconds&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-sort&#34;&gt;Quick Sort&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;quick sort&amp;rsquo; algorithm achieves the same result as &amp;lsquo;selection sort&amp;rsquo;, but is much faster. This particular algorithm sorts an unordered list using recusion instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Specifically it uses the D&amp;amp;C (Divide and Conquer) approach to problem solving.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The process is as follows:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You pick a &amp;lsquo;pivot&amp;rsquo; (a random array index)&lt;/li&gt;&#xA;&lt;li&gt;Loop the array storing items less than the pivot&lt;/li&gt;&#xA;&lt;li&gt;Loop the array storing items greater than the pivot&lt;/li&gt;&#xA;&lt;li&gt;Assuming the &amp;lsquo;less&amp;rsquo; and &amp;lsquo;greater&amp;rsquo; collections are already sorted&lt;/li&gt;&#xA;&lt;li&gt;You can now return &amp;lsquo;less&amp;rsquo; + pivot + &amp;lsquo;greater&amp;rsquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In reality you&amp;rsquo;ll use recursion to then sort both the &amp;lsquo;less&amp;rsquo; and &amp;lsquo;greater&amp;rsquo; arrays using the same algorithm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This ends up being &lt;code&gt;O(n₂)&lt;/code&gt; in the worst case, but can be &lt;code&gt;O(n Log₂ n)&lt;/code&gt; in the better case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The explanation for this, is that the quicksort function takes in a single collection and loops over it. In the process it then splits the collection into three chunks (less, pivot and greater) and it recursively calls itself (i.e. quicksort calls quicksort) on the &amp;lsquo;less&amp;rsquo; and &amp;lsquo;greater&amp;rsquo; chunks, subsequently looping over those collections as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Big O notation helps us to understand the hidden complexity of the algorithm. If you see something like &lt;code&gt;O(n₂)&lt;/code&gt;, then you know that there are nested loops or some kind of recursion happening in order to cause that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now it&amp;rsquo;s worth being aware that Quick Sort&amp;rsquo;s performance is dependent on the pivot you choose. Take a look at some of the example implementations of the quick sort algorithm in the reference list below &lt;a href=&#34;#15&#34;&gt;&amp;ldquo;Gist: Algorithms in Python&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There you&amp;rsquo;ll see we have three implementations: one where we pick the first index every time as the pivot, one where we pick the middle index every time and one where we pick an index at random.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Picking an index at random will give you the best chance of high performance. If you, for example, always pick the first index then you&amp;rsquo;ll have a situation where you&amp;rsquo;re potentially sorting items unnecessarily.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in the best case scenario, if your collection is 10 items long, then it would calculate as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10 * 4 (Log₂10 == 2*2*2*2) = 40 operations&#xA;0.1 * 40 = 4 seconds&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But in the worst case scenario, if your collection was 10 items long, then it could calculate as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;10 * 10 = 100 operations&#xA;0.1 * 100 = 10 seconds&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This has been a very basic introduction to the concept of Big O. Hopefully you&amp;rsquo;ve found it useful and have a greater appreciation for what Big O offers in the way of understanding the performance of particular algorithms (although we&amp;rsquo;ve only really looked at a very small selection).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve seen the following Big O types:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;O(Log n (x))&lt;/code&gt;: log time&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n!)&lt;/code&gt;: factorial time&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n)&lt;/code&gt;: linear time&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(1)&lt;/code&gt;: constant time&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n * n)&lt;/code&gt; (also known as &lt;code&gt;O(n₂)&lt;/code&gt;): selection sort example&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;O(n Log n (x))&lt;/code&gt;: quick sort example&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;There are many more algorithms and calculations for Big O, and as I learn them I&amp;rsquo;ll be sure to update this blog post accordingly. If in the mean time you notice any mistakes, then please feel free to let me know.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/Integralist/9763bded76e7d826535a3caeafc3bdff&#34; target=&#34;_blank&#34;&gt;Gist: Algorithms in Python&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/&#34; target=&#34;_blank&#34;&gt;Beginners Guide to Big O&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/big-o-for-beginners/</guid>
      <link>https://www.integralist.co.uk/posts/big-o-for-beginners/</link>
      <pubDate>Tue, 28 Jun 2016 00:00:00 +0000</pubDate>
      <title>Big O for Beginners</title>
    </item>
    <item>
      <description>&lt;p&gt;For me the perfect developer (if there is such a person) has these qualities:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Friendly&lt;/strong&gt;: is respected and liked by all they work with and are always approachable (even in times of stress)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Humble&lt;/strong&gt;: has great humilty and is not driven by ego&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Calm&lt;/strong&gt;: doesn&amp;rsquo;t get emotive within discussions (including discussions that are both in their favour and those that aren&amp;rsquo;t)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Understanding&lt;/strong&gt;: appreciates that business requirements do change regularly and that there are no perfect scenarios; so is able to adapt to problematic situations in the appropriate manner&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Agile&lt;/strong&gt;: recognises when they are potentially moving down a rabbit hole/time sink/yak shave and will successfully re-evaluate the situation and refocus their attention&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Patient&lt;/strong&gt;: appreciates that no dev is born equal and so varying soft/practical skills will be encountered&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Experienced&lt;/strong&gt;: has a wide ranging skill set with relevant practical experience and most importantly realises the fundamentals of simple code design and recognised patterns&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Consistent&lt;/strong&gt;: by being consistent in their development approach they faciliate easier rotation of developers when resources are restricted/restructured&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Wise&lt;/strong&gt;: knows &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;where&lt;/em&gt; a particular technology is appropriate to use (and when not appropriate)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Analytical&lt;/strong&gt;: is pragmatic and can break down complex problems into logical smaller tasks&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Articulate&lt;/strong&gt;: able to communicate clearly their ideas to people of all technical levels&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Open&lt;/strong&gt;: continuous documentation and visibility into design and development progress; ensuring good communication&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Reasonable&lt;/strong&gt;: understands a problem&amp;rsquo;s sense of proportion; what&amp;rsquo;s important and what isn&amp;rsquo;t (e.g. when something is a big deal and worth pressing; and when it isn&amp;rsquo;t and so not prematurely raising red flags)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Passionate&lt;/strong&gt;: enjoys their craft; always keen/open to new experiences and learning new things&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/the-perfect-developer/</guid>
      <link>https://www.integralist.co.uk/posts/the-perfect-developer/</link>
      <pubDate>Fri, 27 May 2016 00:00:00 +0000</pubDate>
      <title>The Perfect Developer Qualities</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine I have a &lt;code&gt;master&lt;/code&gt; branch with one commit:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is a single &lt;code&gt;README.md&lt;/code&gt; file with the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;- A: 1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now imagine I have a branch from &lt;code&gt;master&lt;/code&gt; called &lt;code&gt;feat/foo&lt;/code&gt; and in that branch I&amp;rsquo;ve made 3 additional commits:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* 41d4115 - Add C (also revert A)&#xA;* 9e5626c - Modify A&#xA;* 8e7965e - Add B&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The contents of the &lt;code&gt;README.md&lt;/code&gt; file is now:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;- A: 1&#xA;- B: 2&#xA;- C: 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Just to quickly clarify, you&amp;rsquo;ll notice throughout this post that I use the command &lt;code&gt;git lg&lt;/code&gt; which is actually an alias I have set within my &lt;code&gt;~/.gitconfig&lt;/code&gt; that uses &lt;code&gt;git log&lt;/code&gt; but modifies its behaviour with some additional git flags:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;log --graph --pretty=format:&#39;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset&#39; --abbrev-commit --date=relative&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;git-merge&#34;&gt;&lt;code&gt;git merge&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;git merge&lt;/code&gt; is the standard workhorse for merging branches in git. It&amp;rsquo;ll try to resolve the differences between the two branches the best way it can.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the source branch &lt;code&gt;feat/foo&lt;/code&gt; (the branch you want to merge from) can be merged &lt;em&gt;cleanly&lt;/em&gt; (e.g. there are no major diverges from the destination branch &lt;code&gt;master&lt;/code&gt;, which is the branch the changes are being merged into), then git will be able to perform a simple &amp;ldquo;fast-forward&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What &amp;ldquo;fast-forward: means is that git will change the &lt;code&gt;HEAD&lt;/code&gt; (on the destination branch) to point to the new latest commit, and all the other commits from your source branch will also appear in the git log/history of the destination branch.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;HEAD&lt;/code&gt; is an alias that points to a commit (typically &lt;code&gt;HEAD&lt;/code&gt; is the latest commit in your branch). Even the branch name itself is an alias that refers to a commit (&lt;em&gt;most things&lt;/em&gt; in git do simply resolve to commits). This is why when you have a long branch name, instead of &lt;code&gt;git push origin really-long-branch-name&lt;/code&gt; you can just use &lt;code&gt;git push origin head&lt;/code&gt; and git will figure out which branch you&amp;rsquo;re on&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you check &lt;code&gt;git lg&lt;/code&gt; after doing a &lt;code&gt;git merge feat/foo&lt;/code&gt;, you should see something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* 41d4115 - (HEAD -&amp;gt; master, origin/feat/foo, feat/foo) Add C (also revert A)&#xA;* 9e5626c - Modify A&#xA;* 8e7965e - Add B&#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see all the commits from &lt;code&gt;feat/foo&lt;/code&gt; were replayed onto &lt;code&gt;master&lt;/code&gt; successfully.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you might not realise that there is a short cut to checking out a branch and then merging another branch into it: &lt;code&gt;git merge &amp;lt;source&amp;gt; &amp;lt;destination&amp;gt;&lt;/code&gt;, which is the same as doing &lt;code&gt;git checkout &amp;lt;destination&amp;gt;&lt;/code&gt; followed by &lt;code&gt;git merge &amp;lt;source&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;git-merge-no-ff-edit&#34;&gt;&lt;code&gt;git merge --no-ff --edit&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s say you wanted a &amp;ldquo;merge commit&amp;rdquo; to happen (i.e. merge commits typically only occur if there has been a divergence between the branches which means git has to resolve the problem for you), then you can force git to use a &amp;ldquo;merge commit&amp;rdquo; even when there is no need for one (as is the case for me here).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using our previous example, which merged cleanly, let&amp;rsquo;s say that a merge commit is what we wanted to have happen. Assuming you&amp;rsquo;ve not pushed the branch to a remote, then you can safely go back to before the merge occurred using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git reset --hard 75eb1cb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;75eb1cb&lt;/code&gt; being my first commit in &lt;code&gt;master&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;git-reset&#34;&gt;&lt;code&gt;git reset&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to understand how &lt;code&gt;git reset&lt;/code&gt; works, as it has three flags and if not used correctly could have bad side effects. The flags are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;--soft&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--mixed&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--hard&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The way reset works is that you use one of the above flags, followed by the commit you want to reset the &lt;code&gt;HEAD&lt;/code&gt; back to. So in our case we used the commit &lt;code&gt;75eb1cb&lt;/code&gt;, which was our very first commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I had used the &lt;code&gt;--soft&lt;/code&gt; flag instead, then it would have reset the &lt;code&gt;HEAD&lt;/code&gt; back to the first commit, but any other commits that happened since would have their changes staged together in our git &amp;lsquo;index&amp;rsquo; waiting to be committed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I had used the &lt;code&gt;--mixed&lt;/code&gt; flag instead, then it would have reset the &lt;code&gt;HEAD&lt;/code&gt; back to the first commit, but any other commits that happened since would have their changes applied to the working directory, ready for us to choose which changes to be added to the index (i.e. staged) and then finally committed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When using &lt;code&gt;--hard&lt;/code&gt; though, any of the changes that came after the commit being reset to, are lost. They&amp;rsquo;re not sitting in your staging index, nor are they available within your working directory either.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So be careful whenever using the &lt;code&gt;--hard&lt;/code&gt; flag.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;force-the-merge-commit&#34;&gt;Force the merge commit&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;re back to where we were originally (a separate &lt;code&gt;feat/foo&lt;/code&gt; branch and a &lt;code&gt;master&lt;/code&gt; branch with a single commit), we can look at how to force a merge commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To force a merge commit you&amp;rsquo;ll need to use the &lt;code&gt;--no-ff&lt;/code&gt; flag and then also use the &lt;code&gt;--edit&lt;/code&gt; flag to allow you to modify the default merge commit message (otherwise git will provide its own commit message which is nearly always not useful or descriptive):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git merge --edit --no-ff feat/foo &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;--edit&lt;/code&gt; doesn&amp;rsquo;t work without &lt;code&gt;--no-ff&lt;/code&gt;, unless there is a &lt;em&gt;genuine&lt;/em&gt; merge conflict&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now if I look at my &lt;code&gt;git lg&lt;/code&gt; I can see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;*   97f1257 - (HEAD -&amp;gt; master) My custom merge commit message for &#39;feat/foo&#39;&#xA;|\  &#xA;| * 41d4115 - (origin/feat/foo, feat/foo) Add C (also revert A)&#xA;| * 9e5626c - Modify A&#xA;| * 8e7965e - Add B&#xA;|/  &#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see all the commits from &lt;code&gt;feat/foo&lt;/code&gt; were replayed onto &lt;code&gt;master&lt;/code&gt; successfully, but now you&amp;rsquo;re able to more easily distinguish the three commits came from another branch (if using my &lt;code&gt;git lg&lt;/code&gt; alias). Which is one of the main reasons to force a merge commit using &lt;code&gt;--no-ff&lt;/code&gt; as it really helps keep a varied branch history.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice &lt;code&gt;git log&lt;/code&gt; will also show in its output for the merge commit&lt;br&gt;&#xA;a field like &lt;code&gt;Merge: 75eb1cb 8e7965e 9e5626c 41d4115&lt;/code&gt;&lt;br&gt;&#xA;Which helps (at a glance) to know more about what commits are inside the merge commit&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;git-branch-contains&#34;&gt;&lt;code&gt;git branch --contains&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following command can be useful in locating where a commit has come from:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git branch --contains 9e5626c&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In our case this will indicate that the commit we specified is part of our &lt;code&gt;master&lt;/code&gt; branch. Now when you use &lt;code&gt;--contains&lt;/code&gt; with a commit such as &lt;code&gt;9e5626c&lt;/code&gt; (which was merged in from our feature branch) you&amp;rsquo;ll see that git recognises this commit is part of multiple branches †.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† until you delete the branch (e.g. &lt;code&gt;git branch -D feat/foo&lt;/code&gt;)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;losing-useful-history&#34;&gt;Losing useful history&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s also worth mentioning, that even after the &lt;code&gt;feat/foo&lt;/code&gt; branch has been deleted, git will still show (via &lt;code&gt;git log --graph&lt;/code&gt;) those commits from our &lt;code&gt;feat/foo&lt;/code&gt; branch as coming from an alternative path/branch history.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a useful bit of information that can be lost when using other tools such as &lt;code&gt;git rebase&lt;/code&gt; or &lt;code&gt;git merge --squash&lt;/code&gt;, so you should discuss with your team what type of information you feel is useful to have when you look back at a project&amp;rsquo;s git history before forging ahead with any one of the strategies I cover here.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, some teams don&amp;rsquo;t find being able to see that a set of commits actually came from another branch very useful: considering all commits/features should generally come in from separate branches/Pull Requests. So the use of rebase or squash isn&amp;rsquo;t a concern for them. For a team like this, an aesthetically &amp;lsquo;cleaner&amp;rsquo; git commit history is preferred.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, in teams where I&amp;rsquo;ve worked and they&amp;rsquo;ve utilised a &amp;lsquo;squash&amp;rsquo; strategy (see &lt;a href=&#34;#4&#34;&gt;below&lt;/a&gt; for more details), we&amp;rsquo;ve used the following structure for our commit message so it&amp;rsquo;s clearer what&amp;rsquo;s been squashed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Closes #123 - New Feature X&#xA;&#xA;Squashed commit of the following:&#xA;&#xA;commit c7e4145f6e95e51fcff79d6b3476bcb19c058071&#xA;commit 3275f1805c4f82298676aa3c61db8c65ee9f3428&#xA;commit bb50fb69c2d131d0126fa9ae018377e6451678e2&#xA;commit 7ceb49c352d812a91db0e87a8ed4c4cf426c0365&#xA;commit 86d1de3c5133a403edf45343081353055c02b454&#xA;commit 8f48e5b3c43acf71e8abab4b821cfdc66447b732&#xA;commit ed857784feff091ece52d906e311ef7f64a49c3d&#xA;commit a277e60c39333a55134c3e3ef6d97076f9bc8370&#xA;commit dd7e1973fe91f29887928aad9d991be24efb143a&#xA;commit ff7e7dabf745ac4d73b52644c3d29ea05d5c318f&#xA;commit 36f1c5bc5949f01117c1d57e6ab12f05c2a202f5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;git-merge-squash&#34;&gt;&lt;code&gt;git merge --squash&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So what if you don&amp;rsquo;t want all those commits in your &lt;code&gt;master&lt;/code&gt;? You could instead &amp;ldquo;squash&amp;rdquo; all the commits down into a single commit using the &lt;code&gt;--squash&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git merge --squash feat/foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now what this does is take my changes from the source branch &lt;code&gt;feat/foo&lt;/code&gt; and automatically squashes those separate commits into a single change that&amp;rsquo;s placed into the staging area of my destination branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These collection of changes &lt;em&gt;now&lt;/em&gt; appear as a single change to the file. They aren&amp;rsquo;t actually &lt;em&gt;merged&lt;/em&gt; yet. So you have the opportunity to change the commit message:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git commit -m &amp;quot;your own custom commit message&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;git-rebase&#34;&gt;&lt;code&gt;git rebase&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;git rebase&lt;/code&gt; feature in essence is solving the same problem as &lt;code&gt;git merge&lt;/code&gt; (they both integrate a set of changes), but they do them in fundamentally different ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With &lt;code&gt;git merge&lt;/code&gt; a merge commit is utilised to resolve conflicts and so is considered &lt;em&gt;non-destructive&lt;/em&gt;. What this means is that the commits within either branch (destination or source) aren&amp;rsquo;t modified in any way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With &lt;code&gt;git rebase&lt;/code&gt; the source branch commits are placed &lt;em&gt;before&lt;/em&gt; the destination branch&amp;rsquo;s commits, but also the source commits are recreated inside the destination branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look and see what this does for us:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase feat/foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see that as there were no conflicts, git was able to &amp;ldquo;fast-forward&amp;rdquo; the commits. So in theory this is no different right now from originally doing &lt;code&gt;git merge feat/foo&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what if &lt;code&gt;master&lt;/code&gt; had a new change committed to it, and this change happened &lt;em&gt;after&lt;/em&gt; we had branched off with &lt;code&gt;feat/foo&lt;/code&gt;? For example, I&amp;rsquo;ll add a second commit to &lt;code&gt;master&lt;/code&gt; that changes &lt;code&gt;- A: 1&lt;/code&gt; to &lt;code&gt;- A: 9&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I run &lt;code&gt;git rebase feat/foo&lt;/code&gt; I should see we get a merge conflict and one that git doesn&amp;rsquo;t know how to resolve:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;First, rewinding head to replay your work on top of it...&#xA;Applying: A to 9&#xA;Using index info to reconstruct a base tree...&#xA;M    README.md&#xA;Falling back to patching base and 3-way merge...&#xA;Auto-merging README.md&#xA;CONFLICT (content): Merge conflict in README.md&#xA;error: Failed to merge in the changes.&#xA;Patch failed at 0001 A to 9&#xA;The copy of the patch that failed is found in: .git/rebase-apply/patch&#xA;&#xA;When you have resolved this problem, run &amp;quot;git rebase --continue&amp;quot;.&#xA;If you prefer to skip this patch, run &amp;quot;git rebase --skip&amp;quot; instead.&#xA;To check out the original branch and stop rebasing, run &amp;quot;git rebase --abort&amp;quot;.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the information git has given us that it first rewinded &lt;code&gt;master&lt;/code&gt; back to the first commit &lt;code&gt;75eb1cb&lt;/code&gt; in order for it to place our &lt;code&gt;feat/foo&lt;/code&gt; commits on top of it (as that initial commit is where our branch originally forked from).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there we can see once git replayed our &lt;code&gt;feat/foo&lt;/code&gt; commits on top of &lt;code&gt;75eb1cb&lt;/code&gt; that it then tried to apply the new commit that &lt;code&gt;feat/foo&lt;/code&gt; didn&amp;rsquo;t have (e.g. &lt;code&gt;Applying: A to 9&lt;/code&gt;) and it failed to do so.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Git tells us that there was a merge conflict:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;CONFLICT (content): Merge conflict in README.md&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s up to us to open &lt;code&gt;README.md&lt;/code&gt; and to resolve the conflict ourself. When I open the file I see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; 41d411564c1dc3106f03427d1b5920d05d95e037&#xA;- A: 1&#xA;- B: 2&#xA;- C: 3&#xA;||||||| merged common ancestors&#xA;- A: 1&#xA;=======&#xA;- A: 9&#xA;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; A to 9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So the above shows the file is split into three:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; &amp;lt;commit_hash&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;||||||| merged common ancestors&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;lt;commit_message&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;I know that I&amp;rsquo;m happy for the line &lt;code&gt;- A: 1&lt;/code&gt; (which was changed in my &lt;code&gt;feat/foo&lt;/code&gt; branch commit &lt;code&gt;41d4115&lt;/code&gt;) to be changed to &lt;code&gt;- A: 9&lt;/code&gt; (which was changed in &lt;code&gt;master&lt;/code&gt; after I originally branched from it). So I manually make that change by deleting all the added noise (e.g. &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; and &lt;code&gt;||||||| merged common ancestors&lt;/code&gt; etc) so I&amp;rsquo;m left with just the content the file should be expected to have now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I update it to look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;- A: 9&#xA;- B: 2&#xA;- C: 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I now must run the following commands:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git add README.md&lt;/code&gt; (as I&amp;rsquo;ve made a change to the file at this point in time)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git rebase --continue&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We see that git is trying again now to apply the commit (but this time there is no merge conflict info inside of the README) and so we see the output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Applying: A to 9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now when looking at the output from &lt;code&gt;git lg&lt;/code&gt; I see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* 7c001cd - (HEAD -&amp;gt; master) A to 9&#xA;* 41d4115 - (origin/feat/foo, feat/foo) Add C (also revert A)&#xA;* 9e5626c - Modify A&#xA;* 8e7965e - Add B&#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This shows that the changes from &lt;code&gt;feat/foo&lt;/code&gt; where replayed directly on top of &lt;code&gt;75eb1cb&lt;/code&gt;. Otherwise if we didn&amp;rsquo;t use git&amp;rsquo;s rebase feature but a standard &lt;code&gt;git merge&lt;/code&gt;, we could&amp;rsquo;ve ended up with a git history that looked like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* 41d4115 - (origin/feat/foo, feat/foo) Add C (also revert A)&#xA;* 9e5626c - Modify A&#xA;* 8e7965e - Add B&#xA;* 65553e0 - (HEAD -&amp;gt; master) A to 9&#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the &lt;code&gt;feat/foo&lt;/code&gt; commits are on top of the &lt;code&gt;A to 9&lt;/code&gt; commit and that might not necessarily be what we want to have happen.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it&amp;rsquo;s usually better to use &lt;code&gt;git pull --rebase &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;&lt;/code&gt; as this will ensure that you get the latest copy of changes for the specified branch (as apposed to &lt;code&gt;git rebase &amp;lt;branch&amp;gt;&lt;/code&gt; which will just be the local copy of that branch (remember &lt;code&gt;git pull&lt;/code&gt; is an abstraction on top of &lt;code&gt;git fetch&lt;/code&gt;, then &lt;code&gt;git merge&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;git-rebase-interactive&#34;&gt;&lt;code&gt;git rebase --interactive&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;--interactive&lt;/code&gt; flag is useful for letting us rewrite our git history. We&amp;rsquo;re able to move the order of our commits as well as squash commits down and change their recorded message.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s assume we want to squash all but the first commit in our &lt;code&gt;feat/foo&lt;/code&gt; branch. By that I mean we currently have:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* b4f9dfd - (HEAD -&amp;gt; feat/foo) Add C (also revert A)&#xA;* 7354a41 - Modify A&#xA;* c321b40 - Add B&#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s say we want &amp;ldquo;Add B&amp;rdquo;, &amp;ldquo;Modify A&amp;rdquo; and &amp;ldquo;Add C (also revert A)&amp;rdquo; squashed into one commit. To do this we need to locate the parent commit of the earliest commit we want to squash.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So &amp;ldquo;Add B&amp;rdquo; is the earliest commit we want as part of the squash, so the parent commit is &amp;ldquo;README&amp;rdquo;. To action the rebase let&amp;rsquo;s run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase --interactive 75eb1cb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This drops us into an editor with the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pick c321b40 Add B&#xA;pick 7354a41 Modify A&#xA;pick b4f9dfd Add C (also revert A)&#xA;&#xA;# Rebase 75eb1cb..b4f9dfd onto 75eb1cb (3 command(s))&#xA;#&#xA;# Commands:&#xA;# p, pick = use commit&#xA;# r, reword = use commit, but edit the commit message&#xA;# e, edit = use commit, but stop for amending&#xA;# s, squash = use commit, but meld into previous commit&#xA;# f, fixup = like &amp;quot;squash&amp;quot;, but discard this commit&#39;s log message&#xA;# x, exec = run command (the rest of the line) using shell&#xA;# d, drop = remove commit&#xA;#&#xA;# These lines can be re-ordered; they are executed from top to bottom.&#xA;#&#xA;# If you remove a line here THAT COMMIT WILL BE LOST.&#xA;#&#xA;# However, if you remove everything, the rebase will be aborted.&#xA;#&#xA;# Note that empty commits are commented out&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can modify it like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pick c321b40 Add B&#xA;squash 7354a41 Modify A&#xA;squash b4f9dfd Add C (also revert A)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will result in the following combined commit details:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# This is a combination of 3 commits.&#xA;# The first commit&#39;s message is:&#xA;Add B&#xA;&#xA;# This is the 2nd commit message:&#xA;&#xA;Modify A&#xA;&#xA;# This is the 3rd commit message:&#xA;&#xA;Add C (also revert A)&#xA;&#xA;# Please enter the commit message for your changes. Lines starting&#xA;# with &#39;#&#39; will be ignored, and an empty message aborts the commit.&#xA;#&#xA;# Date:      Sun May 15 17:29:32 2016 +0100&#xA;#&#xA;# interactive rebase in progress; onto 75eb1cb&#xA;# Last commands done (3 commands done):&#xA;#    squash 7354a41 Modify A&#xA;#    squash b4f9dfd Add C (also revert A)&#xA;# No commands remaining.&#xA;# You are currently editing a commit while rebasing branch &#39;feat/foo&#39; on &#39;75eb1cb&#39;.&#xA;#&#xA;# Changes to be committed:&#xA;#    modified:   README.md&#xA;#&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if we run &lt;code&gt;git lg -p&lt;/code&gt; we&amp;rsquo;ll see the new squashed commit does indeed contain all the previous commit&amp;rsquo;s contents:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* b63857d - (HEAD -&amp;gt; feat/foo) Add B (16 minutes ago)| &#xA;| diff --git a/README.md b/README.md&#xA;| index 428f59e..f2e26b6 100644&#xA;| --- a/README.md&#xA;| +++ b/README.md&#xA;| @@ -1 +1,3 @@&#xA;|  - A: 1&#xA;| +- B: 2&#xA;| +- C: 3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;git-rebase-onto&#34;&gt;&lt;code&gt;git rebase --onto&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine we&amp;rsquo;ve merged our &lt;code&gt;feat/foo&lt;/code&gt; branch at this point into &lt;code&gt;master&lt;/code&gt; using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git merge --squash feat/foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll need to fix a conflict first for it to be successful&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;master&lt;/code&gt; should now have three commits:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;* 19ec1bb - (HEAD -&amp;gt; master) Merge feat/foo&#xA;* 3fc460b - A to 9&#xA;* 75eb1cb - (origin/master) README&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s the easiest way to delete the middle/second commit &lt;code&gt;3fc460b&lt;/code&gt;? We could use &lt;code&gt;git rebase --interactive&lt;/code&gt; to delete the commit from history, but there is an alternative that&amp;rsquo;s much easier:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase --onto 75eb1cb 3fc460b&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in this scenario you&amp;rsquo;ll get a conflict that you&amp;rsquo;ll need to resolve first (e.g. we&amp;rsquo;re removing a commit that sets A to the value 9 but that change was also pulled into the &lt;code&gt;feat/foo&lt;/code&gt; branch so git isn&amp;rsquo;t sure whether you definitely want that change any more or not), but in most cases you&amp;rsquo;ll likely have a clean rebase&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The basic structure of this command is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase --onto &amp;lt;commit_to_become_new_base&amp;gt; &amp;lt;commit_to_delete&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For more information see the documentation for &lt;code&gt;git rebase&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;man git-rebase&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://git-scm.com/docs/git-rebase&#34; target=&#34;_blank&#34;&gt;git-scm.com/docs/git-rebase&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;git-format-patch&#34;&gt;&lt;code&gt;git format-patch&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At this point you&amp;rsquo;re likely using a service such as &lt;a href=&#34;https://github.com/&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt; or &lt;a href=&#34;https://about.gitlab.com/&#34; target=&#34;_blank&#34;&gt;GitLab&lt;/a&gt; for creating projects and opening pull requests, as apposed to Git&amp;rsquo;s own native pull request feature which is substantially less feature rich than these commercial abstraction layers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But sometimes just accepting a &amp;lsquo;patch&amp;rsquo; from someone and being able to apply it quickly and easily is what you want to do. So that&amp;rsquo;s where &lt;code&gt;git format-patch&lt;/code&gt; comes in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a centralised &lt;code&gt;master&lt;/code&gt; branch and someone has branched off from its &lt;code&gt;HEAD&lt;/code&gt; to a new branch called &lt;code&gt;cool-new-features&lt;/code&gt; and they would like you to merge their changes directly with the centralised repository&amp;rsquo;s &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This person would need to execute the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git format-patch master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can swap the branch &lt;code&gt;master&lt;/code&gt; for any valid commit, alias or range&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What this will end up doing is generating a &amp;lsquo;patch&amp;rsquo; file for each new commit that isn&amp;rsquo;t available in master. Below is an example patch file generated from a test repo I was messing around with, and which actually generated two patch files for me (this being the first one):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;From 64a903d2ed6b4280d4a0914aaf50f014ae05cdd3 Mon Sep 17 00:00:00 2001&#xA;From: Integralist &amp;lt;mark.mcdx@gmail.com&amp;gt;&#xA;Date: Tue, 31 May 2016 08:28:56 +0100&#xA;Subject: [PATCH 1/2] G&#xA;&#xA;---&#xA; foo.txt | 1 +&#xA; 1 file changed, 1 insertion(+)&#xA;&#xA;diff --git a/foo.txt b/foo.txt&#xA;index b1e6722..6f04b1d 100644&#xA;--- a/foo.txt&#xA;+++ b/foo.txt&#xA;@@ -1,3 +1,4 @@&#xA; A&#xA; B&#xA; C&#xA;+G&#xA;-- &#xA;2.7.4&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want a single patch file you can use&lt;br&gt;&#xA;the &lt;code&gt;--stdout&lt;/code&gt; flag and redirect the output to a file&lt;br&gt;&#xA;&lt;code&gt;git format-patch master --stdout &amp;gt; new-feature.patch&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The person who generates the patch file(s) will then need to send them to you (which can be done using &lt;code&gt;git send-email&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git send-email -to devlist@example.org 0001-A.patch&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If it&amp;rsquo;s you sending the patch via git, then you may need to configure git to use your mail server details:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global sendemail.smtpserver smtp.my-isp.com&#xA;git config --global sendemail.smtpserverport 465&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You, as the recipient of the patch file(s), can then review and apply the patch using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout review-new-feature&#xA;cat new-feature.patch | git am # single patch file&#xA;cat *.patch | git am           # multiple patch files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Also of interest, if using GitHub for Pull Requests, is that you can add a &lt;code&gt;.patch&lt;/code&gt; extension to the end of a PR path or commit path for it to generate a patch for you! So you can utilise GitHub for some of the nice &amp;lsquo;review&amp;rsquo; features, but then utilise classic/traditional communication and application of patches if you so choose (maybe for an older/internal system).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you have a GitHub PR URL like &lt;code&gt;https://github.com/my-org/my-repo/pull/123&lt;/code&gt;, then you can convert this into a patch file using &lt;code&gt;https://github.com/my-org/my-repo/pull/123.patch&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Git also offers you the &lt;code&gt;git apply&lt;/code&gt; command to use in place of &lt;code&gt;git am&lt;/code&gt;. The reason being is that &lt;code&gt;git am&lt;/code&gt; actually commits the changes in the patch, whereas &lt;code&gt;git apply&lt;/code&gt; will only affect your working directory, so you&amp;rsquo;ll have the opportunity to stage and commit the changes however you like. Unless you use the &lt;code&gt;--cached&lt;/code&gt; or &lt;code&gt;--index&lt;/code&gt; flags (see &lt;code&gt;man git-apply&lt;/code&gt; for details).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;git apply&lt;/code&gt; also has a &lt;code&gt;--reverse&lt;/code&gt; flag to manipulate the order when applying multiple patchess&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The other difference is that &lt;code&gt;git am&lt;/code&gt; only accepts patch files, whereas &lt;code&gt;git apply&lt;/code&gt; accepts patch files and also output from &lt;code&gt;git diff&lt;/code&gt;. So you have more options available to you that way. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl https://gist.githubusercontent.com/anonymous/x/raw/x/test.diff | git apply&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are so many aspects to merging commits and dealing with git&amp;rsquo;s commit history, that it&amp;rsquo;s difficult to cover everything without people having to mentally store too much information that most of the time you wont utilise.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, I&amp;rsquo;ve not covered anything to do with pulling commits: &lt;code&gt;git pull --strategy&lt;/code&gt;, &lt;code&gt;git pull --squash&lt;/code&gt;, &lt;code&gt;git pull --rebase&lt;/code&gt;, &lt;code&gt;git pull --ff-only&lt;/code&gt; and &lt;code&gt;git pull --no-commit&lt;/code&gt;. Each have their use cases, but I think sometimes you&amp;rsquo;re better picking a single strategy and defining it as a standard within your development team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in one git workflow approach that utilises git&amp;rsquo;s rebasing feature, and I&amp;rsquo;ve used with success in the past at the BBC, then I recommend you have a read of this blog post I wrote a few years ago: &lt;a href=&#34;/posts/github-workflow/&#34;&gt;integralist.co.uk/posts/github-workflow&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve also written about other types of git &amp;ldquo;workflows&amp;rdquo; as part of BBC News&amp;rsquo; &amp;ldquo;Coding Best Practices&amp;rdquo; working group: &lt;a href=&#34;https://github.com/bbc/news-coding-best-practices/blob/master/git-workflow.md&#34; target=&#34;_blank&#34;&gt;github.com/bbc/news-coding-best-practices/git-workflow&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/git-merge-strategies/</guid>
      <link>https://www.integralist.co.uk/posts/git-merge-strategies/</link>
      <pubDate>Sun, 15 May 2016 00:00:00 +0000</pubDate>
      <title>Git Merge Strategies</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I started designing a new microservice that I wanted to write in &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;. The service was to be a JSON RPC service over TCP, and the expected consumer servicer I would build using &lt;a href=&#34;https://www.ruby-lang.org/&#34; target=&#34;_blank&#34;&gt;Ruby&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I had some initial concerns regarding the nature of TCP sockets with a highly scalable and distrubuted set of services (this was to be utilised within the &lt;a href=&#34;http://www.bbc.co.uk/news&#34; target=&#34;_blank&#34;&gt;BBC&lt;/a&gt; so these are genuine concerns to be had for my purposes) and so I decided to do some research.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a few issues that I discovered:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;TCP connections aren&amp;rsquo;t free (so utilise a connection pool)&lt;/li&gt;&#xA;&lt;li&gt;Too many simultaneous requests can exhaust open port/file descriptors&lt;/li&gt;&#xA;&lt;li&gt;If not careful you can end up with orphaned TCP connections (e.g. if no timeouts configured)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Now these are all things that can be worked around (or I could just build the Go service as a HTTP REST service and some of these problems dissapear). But it seems lots of people have been talking about using Google&amp;rsquo;s new open-source RPC framework called &lt;a href=&#34;http://www.grpc.io/&#34; target=&#34;_blank&#34;&gt;gRPC&lt;/a&gt; and I thought what better time to investigate what it can do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Google define gRPC as:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A high performance, open source, general RPC framework that puts mobile and HTTP/2 first&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One of the initial benefits is the ability to be able to define and codify your service requirements via a &lt;code&gt;.proto&lt;/code&gt; file. The proto file is based around another concept Google have been working on known as &lt;a href=&#34;https://developers.google.com/protocol-buffers/docs/overview&#34; target=&#34;_blank&#34;&gt;Protocol Buffers&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In essence, protocol buffers are an open-source mechanism for serializing structured data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have your service &lt;em&gt;defined&lt;/em&gt;, you can utilise a command line compiler to generate stubs and code in multiple programming languages. So you can generate a client and server with the Go programming language, and then using the same &lt;code&gt;.proto&lt;/code&gt; file generate a client/server with Ruby.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Google have built gRPC on top of the &lt;a href=&#34;https://http2.github.io/&#34; target=&#34;_blank&#34;&gt;HTTP/2 standard&lt;/a&gt;, meaning you get features such as bidirectional streaming, flow control, header compression and multiplexing requests over a single TCP connection.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;See &lt;a href=&#34;http://www.grpc.io/posts/principles&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; for Google&amp;rsquo;s &amp;ldquo;motivation and design principles&amp;rdquo; around gRPC&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now the reason for this post is that I didn&amp;rsquo;t find the documentation to be that intuitive. I thought I might be able to help people get started more quickly by detailing the steps in a more succinct fashion than found in Google&amp;rsquo;s documentation, thus opening up gRPC to more users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with this in mind, let&amp;rsquo;s crack on&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;install-grpc&#34;&gt;Install gRPC&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First thing we need to do is install gRPC&amp;rsquo;s C based libraries. Once we have this installed we will later install plugin extensions for other programming languages (such as Go and Ruby, but there are other languages available).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the things I discovered further along in my research of gRPC (and I wish I had known earlier) was that some commands that are utilised by the language extensions are only available when installing gRPC from source. So that&amp;rsquo;s what we&amp;rsquo;ll be doing now:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git clone https://github.com/grpc/grpc.git&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cd grpc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git submodule update --init&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;make&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;make install&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;install-proto-buffer-compiler&#34;&gt;Install Proto Buffer Compiler&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now that we have gRPC installed we also need the compiler for the Protocol Buffer definition file. This is the file that defines our service and which we&amp;rsquo;ll get round to writing shortly. In order to install the compiler you&amp;rsquo;ll first need to make sure you have the &lt;a href=&#34;https://github.com/google/protobuf/tree/master/src&#34; target=&#34;_blank&#34;&gt;requisite dependencies installed&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For myself, running this on Mac OS X I just need XCode installed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sudo xcode-select --install&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once you do that, you can execute the following steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git clone git@github.com:google/protobuf.git&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;./autogen.sh&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;./configure&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;make&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;make check&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sudo make install&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;each Make target took ~10mins each to run&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;hello-world-proto-definition&#34;&gt;Hello World Proto Definition&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Protocol Buffers are designed by Google to be language and platform neutral, and so in theory you can use it with your own RPC implementation. But in reality most people will use gRPC with Protocol Buffers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with that said, here is our service definition written using the latest syntax (&lt;code&gt;proto3&lt;/code&gt;) and I&amp;rsquo;ve named it &lt;code&gt;requester.proto&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;syntax = &amp;quot;proto3&amp;quot;;&#xA;&#xA;package requester;&#xA;&#xA;service Requester {&#xA;  rpc Process (Config) returns (Response) {}&#xA;}&#xA;&#xA;message Config {&#xA;  string data = 1;&#xA;}&#xA;&#xA;message Response {&#xA;  string message = 1;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;see &lt;a href=&#34;https://developers.google.com/protocol-buffers/docs/proto3#specifying-field-types&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; for full proto3 syntax documentation&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In summary it defines an RPC service that exposes a &lt;code&gt;Process&lt;/code&gt; method which can be called remotely. In reality, it&amp;rsquo;s the same &amp;lsquo;Hello World&amp;rsquo; app provided by the gRPC docs but with some changes in identifiers.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;syntax-explanation&#34;&gt;Syntax Explanation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can see the &lt;code&gt;package&lt;/code&gt; statement near the top, which according to Google&amp;rsquo;s docs are used to avoid name clashes between protocol messages; but more specifically it effects the way code is compiled/generated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, in Ruby it&amp;rsquo;ll generate a top level module that utilises that namespace. As you&amp;rsquo;ll see shortly, I have two nested modules with the same name &lt;code&gt;Requester::Requester&lt;/code&gt;. This is because the &lt;code&gt;package&lt;/code&gt; setting is the top level and the nested module name is because that&amp;rsquo;s what I named the &lt;code&gt;service&lt;/code&gt;. So be careful what you name it as the compiled code might not be what you want.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because the design has come from Google you&amp;rsquo;re going to notice lots of design considerations that correlate to their opinions and choices with the Go programming language&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In Go, the other language we&amp;rsquo;re using, the &lt;code&gt;package&lt;/code&gt; value is used (conveniently) as the name of the Go package. Which makes sense as there is a closer correlation in the design of Protocol Buffers and Go vs a dynamic language such as Ruby.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Inside of the &lt;code&gt;service&lt;/code&gt; statement we state that we want an RPC service that has a &lt;code&gt;Process&lt;/code&gt; method and that method accepts something of type &lt;code&gt;Config&lt;/code&gt; and returns something of type &lt;code&gt;Response&lt;/code&gt;. We can then define what &lt;code&gt;Config&lt;/code&gt; and &lt;code&gt;Response&lt;/code&gt; look like, which we do using the &lt;code&gt;message&lt;/code&gt; statement.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to keep things simple I&amp;rsquo;ve only used a single property setting for each message, but there is a rich selection of data types you can utilise. In my simple example both properties have a &lt;code&gt;string&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can then access these properties from your code as a nested object field/property. So in Ruby, for example, if you accepted the message &lt;code&gt;Config&lt;/code&gt; as an argument &lt;code&gt;c&lt;/code&gt; to your &lt;code&gt;Process&lt;/code&gt; method then your code would call &lt;code&gt;c.data&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The numbers assigned to the property (e.g. both &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt; are assigned the value &lt;code&gt;1&lt;/code&gt;) are known as &amp;lsquo;tags&amp;rsquo;. Effectively, tags with a number between 1 and 15 take one byte to encode whereas tags between 16 and 2047 take two bytes to encode.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The idea is that you should reserve the tags 1 through 15 for very frequently occurring message elements. But if you really want all the gory details then I&amp;rsquo;ll refer you to the &lt;a href=&#34;https://developers.google.com/protocol-buffers/docs/encoding&#34; target=&#34;_blank&#34;&gt;encoding documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;auto-generating-service-code&#34;&gt;Auto Generating Service Code&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So at this point we have the option of auto-generating &amp;lsquo;service code&amp;rsquo; for any of the languages gRPC supports, which is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;C&lt;/li&gt;&#xA;&lt;li&gt;C#&lt;/li&gt;&#xA;&lt;li&gt;C++&lt;/li&gt;&#xA;&lt;li&gt;Go&lt;/li&gt;&#xA;&lt;li&gt;Java&lt;/li&gt;&#xA;&lt;li&gt;Node.js&lt;/li&gt;&#xA;&lt;li&gt;Objective-C&lt;/li&gt;&#xA;&lt;li&gt;PHP&lt;/li&gt;&#xA;&lt;li&gt;Python&lt;/li&gt;&#xA;&lt;li&gt;Ruby&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re interested in Go and Ruby as I want to have the RPC service server side running in Go but have the consumer in Ruby. So I&amp;rsquo;ll first generate the Ruby client stub using the &lt;code&gt;protoc&lt;/code&gt; compiler we installed earlier:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;protoc --ruby_out=lib \&#xA;--grpc_out=lib \&#xA;--plugin=protoc-gen-grpc=`which grpc_ruby_plugin` ./requester.proto&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;execute &lt;code&gt;mkdir lib&lt;/code&gt; if that directory doesn&amp;rsquo;t already exist&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This will generate two files &lt;code&gt;requester.rb&lt;/code&gt; and &lt;code&gt;requester_services.rb&lt;/code&gt; inside of the &lt;code&gt;lib&lt;/code&gt; directory we&amp;rsquo;ve specified. The content of those files looks like the following. The first file being &lt;code&gt;requester.rb&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Generated by the protocol buffer compiler.  DO NOT EDIT!&#xA;# source: requester.proto&#xA;&#xA;require &#39;google/protobuf&#39;&#xA;&#xA;Google::Protobuf::DescriptorPool.generated_pool.build do&#xA;  add_message &amp;quot;requester.Config&amp;quot; do&#xA;    optional :name, :string, 1&#xA;  end&#xA;  add_message &amp;quot;requester.Response&amp;quot; do&#xA;    optional :message, :string, 1&#xA;  end&#xA;end&#xA;&#xA;module Requester&#xA;  Config = Google::Protobuf::DescriptorPool.generated_pool.lookup(&amp;quot;requester.Config&amp;quot;).msgclass&#xA;  Response = Google::Protobuf::DescriptorPool.generated_pool.lookup(&amp;quot;requester.Response&amp;quot;).msgclass&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here is the second file &lt;code&gt;requester_services.rb&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Generated by the protocol buffer compiler.  DO NOT EDIT!&#xA;# Source: requester.proto for package &#39;requester&#39;&#xA;&#xA;require &#39;grpc&#39;&#xA;require &#39;requester&#39;&#xA;&#xA;module Requester&#xA;  module Requester&#xA;&#xA;    # TODO: add proto service documentation here&#xA;    class Service&#xA;&#xA;      include GRPC::GenericService&#xA;&#xA;      self.marshal_class_method = :encode&#xA;      self.unmarshal_class_method = :decode&#xA;      self.service_name = &#39;requester.Requester&#39;&#xA;&#xA;      rpc :Process, Config, Response&#xA;    end&#xA;&#xA;    Stub = Service.rpc_stub_class&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll see how to consume these stubs from Ruby in the next section. But now let&amp;rsquo;s move onto how to use &lt;code&gt;protoc&lt;/code&gt; to generate some Golang stubs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;protoc --go_out=plugins=grpc:pb ./requester.proto&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So in the above example the &lt;code&gt;pb&lt;/code&gt; reference is to a folder that has to exist before you run that command. You can name the folder whatever you like obviously, but &lt;code&gt;pb&lt;/code&gt; (protocol buffer) made sense to me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The file that is generated will be named &lt;code&gt;requester.pb.go&lt;/code&gt; and (as with the Ruby code) we&amp;rsquo;ll look at how to consume this file in a following section that demonstrates the Go code examples. But for now let&amp;rsquo;s see the contents of this file (shield your eyes, Go isn&amp;rsquo;t the most concise programming language):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Code generated by protoc-gen-go.&#xA;// source: requester.proto&#xA;// DO NOT EDIT!&#xA;&#xA;/*&#xA;Package requester is a generated protocol buffer package.&#xA;&#xA;It is generated from these files:&#xA;  requester.proto&#xA;&#xA;It has these top-level messages:&#xA;  Config&#xA;  Response&#xA;*/&#xA;package requester&#xA;&#xA;import proto &amp;quot;github.com/golang/protobuf/proto&amp;quot;&#xA;import fmt &amp;quot;fmt&amp;quot;&#xA;import math &amp;quot;math&amp;quot;&#xA;&#xA;import (&#xA;  context &amp;quot;golang.org/x/net/context&amp;quot;&#xA;  grpc &amp;quot;google.golang.org/grpc&amp;quot;&#xA;)&#xA;&#xA;// Reference imports to suppress errors if they are not otherwise used.&#xA;var _ = proto.Marshal&#xA;var _ = fmt.Errorf&#xA;var _ = math.Inf&#xA;&#xA;// This is a compile-time assertion to ensure that this generated file&#xA;// is compatible with the proto package it is being compiled against.&#xA;const _ = proto.ProtoPackageIsVersion1&#xA;&#xA;type Config struct {&#xA;  Name string `protobuf:&amp;quot;bytes,1,opt,name=name&amp;quot; json:&amp;quot;name,omitempty&amp;quot;`&#xA;}&#xA;&#xA;func (m *Config) Reset()                    { *m = Config{} }&#xA;func (m *Config) String() string            { return proto.CompactTextString(m) }&#xA;func (*Config) ProtoMessage()               {}&#xA;func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }&#xA;&#xA;type Response struct {&#xA;  Message string `protobuf:&amp;quot;bytes,1,opt,name=message&amp;quot; json:&amp;quot;message,omitempty&amp;quot;`&#xA;}&#xA;&#xA;func (m *Response) Reset()                    { *m = Response{} }&#xA;func (m *Response) String() string            { return proto.CompactTextString(m) }&#xA;func (*Response) ProtoMessage()               {}&#xA;func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }&#xA;&#xA;func init() {&#xA;  proto.RegisterType((*Config)(nil), &amp;quot;requester.Config&amp;quot;)&#xA;  proto.RegisterType((*Response)(nil), &amp;quot;requester.Response&amp;quot;)&#xA;}&#xA;&#xA;// Reference imports to suppress errors if they are not otherwise used.&#xA;var _ context.Context&#xA;var _ grpc.ClientConn&#xA;&#xA;// This is a compile-time assertion to ensure that this generated file&#xA;// is compatible with the grpc package it is being compiled against.&#xA;const _ = grpc.SupportPackageIsVersion1&#xA;&#xA;// Client API for Requester service&#xA;&#xA;type RequesterClient interface {&#xA;  Process(ctx context.Context, in *Config, opts ...grpc.CallOption) (*Response, error)&#xA;}&#xA;&#xA;type requesterClient struct {&#xA;  cc *grpc.ClientConn&#xA;}&#xA;&#xA;func NewRequesterClient(cc *grpc.ClientConn) RequesterClient {&#xA;  return &amp;amp;requesterClient{cc}&#xA;}&#xA;&#xA;func (c *requesterClient) Process(&#xA;    ctx context.Context, in *Config, opts ...grpc.CallOption&#xA;) (*Response, error) {&#xA;  out := new(Response)&#xA;  err := grpc.Invoke(ctx, &amp;quot;/requester.Requester/Process&amp;quot;, in, out, c.cc, opts...)&#xA;  if err != nil {&#xA;    return nil, err&#xA;  }&#xA;  return out, nil&#xA;}&#xA;&#xA;// Server API for Requester service&#xA;&#xA;type RequesterServer interface {&#xA;  Process(context.Context, *Config) (*Response, error)&#xA;}&#xA;&#xA;func RegisterRequesterServer(s *grpc.Server, srv RequesterServer) {&#xA;  s.RegisterService(&amp;amp;_Requester_serviceDesc, srv)&#xA;}&#xA;&#xA;func _Requester_Process_Handler(&#xA;    srv interface{}, ctx context.Context, dec func(interface{}) error&#xA;) (interface{}, error) {&#xA;  in := new(Config)&#xA;  if err := dec(in); err != nil {&#xA;    return nil, err&#xA;  }&#xA;  out, err := srv.(RequesterServer).Process(ctx, in)&#xA;  if err != nil {&#xA;    return nil, err&#xA;  }&#xA;  return out, nil&#xA;}&#xA;&#xA;var _Requester_serviceDesc = grpc.ServiceDesc{&#xA;  ServiceName: &amp;quot;requester.Requester&amp;quot;,&#xA;  HandlerType: (*RequesterServer)(nil),&#xA;  Methods: []grpc.MethodDesc{&#xA;    {&#xA;      MethodName: &amp;quot;Process&amp;quot;,&#xA;      Handler:    _Requester_Process_Handler,&#xA;    },&#xA;  },&#xA;  Streams: []grpc.StreamDesc{},&#xA;}&#xA;&#xA;var fileDescriptor0 = []byte{&#xA;  // 172 bytes of a gzipped FileDescriptorProto&#xA;  0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2f, 0x4a, 0x2d, 0x2c,&#xA;  0x4d, 0x2d, 0x2e, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0x0b, 0x28,&#xA;  0xc9, 0x70, 0xb1, 0x39, 0xe7, 0xe7, 0xa5, 0x65, 0xa6, 0x0b, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6,&#xA;  0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x4a, 0x2a, 0x5c, 0x1c, 0x41, 0xa9,&#xA;  0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x12, 0x5c, 0xec, 0xb9, 0xa9, 0xc5, 0xc5, 0x89, 0xe9,&#xA;  0x30, 0x25, 0x30, 0xae, 0x91, 0x03, 0x17, 0x67, 0x10, 0xcc, 0x40, 0x21, 0x63, 0x2e, 0xf6, 0x80,&#xA;  0xa2, 0xfc, 0x64, 0xa0, 0x94, 0x90, 0xa0, 0x1e, 0xc2, 0x62, 0x88, 0x25, 0x52, 0xc2, 0x48, 0x42,&#xA;  0x30, 0x93, 0x95, 0x18, 0x9c, 0x8c, 0xb9, 0xa4, 0x32, 0xf3, 0xf5, 0xd2, 0x8b, 0x0a, 0x92, 0xf5,&#xA;  0x52, 0x2b, 0x12, 0x73, 0x0b, 0x72, 0x52, 0x8b, 0x11, 0x0a, 0x9d, 0xf8, 0xe0, 0xa6, 0x07, 0x80,&#xA;  0x9c, 0x1f, 0xc0, 0xb8, 0x88, 0x89, 0x29, 0x28, 0x30, 0x89, 0x0d, 0xec, 0x19, 0x63, 0x40, 0x00,&#xA;  0x00, 0x00, 0xff, 0xff, 0xac, 0xd0, 0xf7, 0x73, 0xdf, 0x00, 0x00, 0x00,&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;ruby-example&#34;&gt;Ruby Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so we&amp;rsquo;ve defined what our service does: it&amp;rsquo;s an RPC service that exposes a &lt;code&gt;Process&lt;/code&gt; method that takes an argument. But what that method returns we&amp;rsquo;ve yet to build (that&amp;rsquo;s not the responsibility of the definition file).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve used the &lt;code&gt;protoc&lt;/code&gt; compiler to auto-generate some code stubs for us, which handle the setting up of the service. So let&amp;rsquo;s see how we consume that from Ruby, we&amp;rsquo;re going to need the following files:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Gemfile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;server.rb&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;client.rb&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This is what the contents of those files look like&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;gemfile&#34;&gt;Gemfile&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;source &amp;quot;https://rubygems.org/&amp;quot;&#xA;&#xA;gem &amp;quot;grpc&amp;quot;, &amp;quot;~&amp;gt; 0.11&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We only have one dependency, which is the &lt;code&gt;grpc&lt;/code&gt; extension.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;server-rb&#34;&gt;server.rb&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$: &amp;lt;&amp;lt; File.join(File.dirname(__FILE__), &amp;quot;lib&amp;quot;)&#xA;&#xA;require &amp;quot;grpc&amp;quot;&#xA;require &amp;quot;requester_services&amp;quot;&#xA;&#xA;class RequesterServer &amp;lt; Requester::Requester::Service&#xA;  def process(config, _unused_call)&#xA;    Requester::Response.new(message: &amp;quot;Hello #{config.name}&amp;quot;)&#xA;  end&#xA;end&#xA;&#xA;s = GRPC::RpcServer.new&#xA;s.add_http2_port(&amp;quot;0.0.0.0:50051&amp;quot;, :this_port_is_insecure)&#xA;s.handle(RequesterServer)&#xA;s.run_till_terminated&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So same set of dependencies pulled in, like with the client. But this time we&amp;rsquo;re creating a new instance of a class that inherits from our &lt;code&gt;Requester::Requester::Service&lt;/code&gt; auto-generated class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is similar in essence to the Template Method Pattern, where we&amp;rsquo;re now able to define the implementation of the method type &lt;code&gt;process&lt;/code&gt;. But one thing to remember is that you need the 2nd argument &lt;code&gt;_unused_call&lt;/code&gt; that&amp;rsquo;s passed into the &lt;code&gt;process&lt;/code&gt; method. Remove it and things will break.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why? I&amp;rsquo;ve actually no idea. I&amp;rsquo;ve found nothing in the documentation that explains this, and I&amp;rsquo;ve sifted through the source code and nothing I could grok to understand why this second (seemingly pointless) argument is there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here we create a new gRPC server instance (&lt;code&gt;GRPC::RpcServer&lt;/code&gt;). We then specify the address and port we want the server to listen to. Don&amp;rsquo;t be fooled in the specific nature of &amp;lsquo;http2&amp;rsquo; in the method &lt;code&gt;add_http2_port&lt;/code&gt;, there is no &lt;code&gt;add_http_port&lt;/code&gt; or alternative method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, as before, the &lt;code&gt;:this_port_is_insecure&lt;/code&gt; is required. I don&amp;rsquo;t really like the design of the code here, but I guess what can you expect from low-level programmers designing code for dynamic languages they typically don&amp;rsquo;t use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Next we specify our &lt;code&gt;RequesterServer&lt;/code&gt; to be the instance that handles any incoming requests. Finally we tell the server to run until it&amp;rsquo;s terminated via a signal such as &lt;code&gt;INT&lt;/code&gt; or &lt;code&gt;TERM&lt;/code&gt; (&lt;a href=&#34;http://www.rubydoc.info/github/grpc/grpc/7131c62/GRPC/RpcServer#run_till_terminated-instance_method&#34; target=&#34;_blank&#34;&gt;documented here&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To run this program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bundle install&#xA;bundle exec ruby server.rb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You wont see anything in the output, so let&amp;rsquo;s move onto the client code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;client-rb&#34;&gt;client.rb&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$: &amp;lt;&amp;lt; File.join(File.dirname(__FILE__), &amp;quot;lib&amp;quot;)&#xA;&#xA;require &amp;quot;grpc&amp;quot;&#xA;require &amp;quot;requester_services&amp;quot;&#xA;&#xA;stub = Requester::Requester::Stub.new(&amp;quot;localhost:50051&amp;quot;, :this_channel_is_insecure)&#xA;msg = stub.process(Requester::Config.new(name: &amp;quot;Mark&amp;quot;)).message&#xA;p &amp;quot;Greeting: #{msg}&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here we&amp;rsquo;re loading our grpc dependency and the service stub that was auto-generated for us. Notice that because my protocol buffer definition file specified the package as &lt;code&gt;requester&lt;/code&gt; and the file itself was called &lt;code&gt;requester&lt;/code&gt; I&amp;rsquo;ve now got this ugly namespace &lt;code&gt;Requester::Requester&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, just be aware of what you&amp;rsquo;re naming things because to be honest that double named module is annoying for me to look at. I left it like that to demonstrate why it&amp;rsquo;s important to name things well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that we pass in &lt;code&gt;:this_channel_is_insecure&lt;/code&gt; to the &lt;code&gt;Stub.new&lt;/code&gt; method. This isn&amp;rsquo;t an arbitrary value, it needs to be exactly that value otherwise you&amp;rsquo;ll see errors. I&amp;rsquo;ve yet to look into using HTTPS/TLS but if you&amp;rsquo;re interested, then you can find the relevant details on the &lt;a href=&#34;http://www.grpc.io/docs/guides/auth.html&#34; target=&#34;_blank&#34;&gt;authentication documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we create a new instance of our service, we can now access the &lt;code&gt;process&lt;/code&gt; method that is exposed by our RPC service. Convention in Ruby is lowercase method names, so although we defined it as &lt;code&gt;Process&lt;/code&gt; it&amp;rsquo;s accessed as &lt;code&gt;process&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We pass into &lt;code&gt;process&lt;/code&gt; the expected &lt;code&gt;Config&lt;/code&gt; &amp;lsquo;type&amp;rsquo; (Ruby doesn&amp;rsquo;t have types as part of the language so they&amp;rsquo;ve provided us a module/namespace instead to mimic this feature), and finally we call the &lt;code&gt;message&lt;/code&gt; property on the returned object (remember we defined a Response in our protocol buffer definition file that had a &lt;code&gt;message&lt;/code&gt; field).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To run this program:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bundle install&#xA;bundle exec ruby client.rb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which should result in the output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;Greeting: Hello Mark&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;go-example&#34;&gt;Go Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We can set up our services to use Go completely or we can mix and match. But let&amp;rsquo;s see how to use both the client and server from Go. As with Ruby, we&amp;rsquo;ve defined what our service does: it&amp;rsquo;s an RPC service that exposes a &lt;code&gt;Process&lt;/code&gt; method that takes an argument. But what that method returns we&amp;rsquo;ve yet to build.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve used the &lt;code&gt;protoc&lt;/code&gt; compiler to auto-generate some code stubs for us, which handle the setting up of the service. So let&amp;rsquo;s see how we consume that from Go, we&amp;rsquo;re going to need the following files:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;server.go&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;client.go&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;server-go&#34;&gt;server.go&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net&amp;quot;&#xA;&#xA;  pb &amp;quot;github.com/integralist/test-grpc-custom/pb&amp;quot;&#xA;  &amp;quot;golang.org/x/net/context&amp;quot;&#xA;  &amp;quot;google.golang.org/grpc&amp;quot;&#xA;)&#xA;&#xA;const (&#xA;  port = &amp;quot;:50051&amp;quot;&#xA;)&#xA;&#xA;type server struct{}&#xA;&#xA;func (s *server) Process(ctx context.Context, in *pb.Config) (*pb.Response, error) {&#xA;  return &amp;amp;pb.Response{Message: &amp;quot;Hello &amp;quot; + in.Name}, nil&#xA;}&#xA;&#xA;func main() {&#xA;  lis, err := net.Listen(&amp;quot;tcp&amp;quot;, port)&#xA;  if err != nil {&#xA;    log.Fatalf(&amp;quot;failed to listen: %v&amp;quot;, err)&#xA;  }&#xA;  s := grpc.NewServer()&#xA;  pb.RegisterRequesterServer(s, &amp;amp;server{})&#xA;  s.Serve(lis)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So the Go variation is fairly straight forward, our &lt;code&gt;main&lt;/code&gt; function listens on the specified port and we start up a new grpc server instance.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there we take the protocol buffer &lt;code&gt;pb/requester.pb.go&lt;/code&gt; that was generated by the &lt;code&gt;protoc&lt;/code&gt; compiler and call a pre-supplied &lt;code&gt;pb.RegisterRequesterServer&lt;/code&gt; method and pass in a data structure for it to utilise along with the grpc server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the &lt;code&gt;server&lt;/code&gt; struct type we associate the required &lt;code&gt;Process&lt;/code&gt; method and define its behaviour. In this case, similar to the Ruby version, we create an instance of the &lt;code&gt;Response&lt;/code&gt; type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To run this program, execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go run server.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;client-go&#34;&gt;client.go&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;os&amp;quot;&#xA;&#xA;  pb &amp;quot;github.com/integralist/test-grpc-custom/pb&amp;quot;&#xA;  &amp;quot;golang.org/x/net/context&amp;quot;&#xA;  &amp;quot;google.golang.org/grpc&amp;quot;&#xA;)&#xA;&#xA;const (&#xA;  address     = &amp;quot;localhost:50051&amp;quot;&#xA;  defaultName = &amp;quot;world&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  conn, err := grpc.Dial(address, grpc.WithInsecure())&#xA;  if err != nil {&#xA;    log.Fatalf(&amp;quot;did not connect: %v&amp;quot;, err)&#xA;  }&#xA;  defer conn.Close()&#xA;  c := pb.NewRequesterClient(conn)&#xA;&#xA;  name := defaultName&#xA;  if len(os.Args) &amp;gt; 1 {&#xA;    name = os.Args[1]&#xA;  }&#xA;  r, err := c.Process(context.Background(), &amp;amp;pb.Config{Name: name})&#xA;  if err != nil {&#xA;    log.Fatalf(&amp;quot;could not greet: %v&amp;quot;, err)&#xA;  }&#xA;  log.Printf(&amp;quot;Greeting: %s&amp;quot;, r.Message)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With the server program running we can now execute our client to call the server&amp;rsquo;s &lt;code&gt;Process&lt;/code&gt; method. Again, in summary, we use gRPC&amp;rsquo;s own &lt;code&gt;Dial&lt;/code&gt; method to call the specified address. The second argument disables the transport security for this particular connection. If you want HTTPS/TLS encryption then you&amp;rsquo;ll need to read the documentation for those details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We create a new instance of the auto-generated client, and call the &lt;code&gt;Process&lt;/code&gt; method. Passing along the auto-generated &lt;code&gt;Config&lt;/code&gt; type with the data we want it to receive.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;pb&lt;/code&gt; identifier references the auto-generated protocol buffer package (&lt;code&gt;pb &amp;quot;github.com/integralist/test-grpc-custom/pb&amp;quot;&lt;/code&gt;), and as you&amp;rsquo;ll probably already know this path is unique to your local setup and where you created that package.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To run this program, execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go run client.go Mark&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which should result in the output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;Greeting: Hello Mark&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you leave off the argument &amp;ldquo;Mark&amp;rdquo;&lt;br&gt;&#xA;then the output will default to &amp;ldquo;Hello world&amp;rdquo; instead&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So there you go. Hopefully you&amp;rsquo;ve found this break down useful. The principles of gRPC seem promising, and although I&amp;rsquo;m not keen on the design of the auto-generated code being not as &amp;lsquo;idiomatic&amp;rsquo; as you&amp;rsquo;d expect for a language such as Ruby (I&amp;rsquo;m not sure what the other language implementations are like) I still think this could be an interesting evolution of the microservices movement.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;update&#34;&gt;Update&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are alternatives that work in a similar fashion, one of which is &lt;a href=&#34;https://thrift.apache.org/&#34; target=&#34;_blank&#34;&gt;Apache Thrift&lt;/a&gt; and is defined as being a &amp;ldquo;software framework, for scalable cross-language services development&amp;rdquo;. But unfortunately it doesn&amp;rsquo;t support the Go programming language, which is a requirement for me. But interesting nonetheless.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/grpc-for-beginners/</guid>
      <link>https://www.integralist.co.uk/posts/grpc-for-beginners/</link>
      <pubDate>Mon, 11 Apr 2016 00:00:00 +0000</pubDate>
      <title>gRPC for Beginners</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a quick post to demonstrate how I use a simple &lt;a href=&#34;https://www.gnu.org/software/bash/&#34; target=&#34;_blank&#34;&gt;Bash&lt;/a&gt; shell script to report when web pages are failing (e.g. returning a non-200 HTTP status code). It does this by sending notifications of the URL which returned a non-200 status code into a remote application (in my case &lt;a href=&#34;https://slack.com/&#34; target=&#34;_blank&#34;&gt;Slack&lt;/a&gt;; but you could modify the script to suit whatever service you happen to be using).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I run this script via &lt;a href=&#34;https://jenkins-ci.org/&#34; target=&#34;_blank&#34;&gt;Jenkins CI&lt;/a&gt; on a five minute cron. The inspiration came from &lt;a href=&#34;https://twitter.com/charlierevett&#34; target=&#34;_blank&#34;&gt;Charlie Revett&lt;/a&gt; who wrote a &lt;a href=&#34;https://nodejs.org/&#34; target=&#34;_blank&#34;&gt;nodejs&lt;/a&gt; package called &lt;a href=&#34;http://github.com/revett/watchtower/&#34; target=&#34;_blank&#34;&gt;Watchtower&lt;/a&gt;. I like shell scripts (not so much Node) and so I decided, for no real good reason, to replicate his package in Bash.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-does-it-work&#34;&gt;How does it work?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The script has the following steps:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Cleanup: remove any temporary files created during a previous run&lt;/li&gt;&#xA;&lt;li&gt;Retrieve: curl the remote endpoints in parallel&lt;/li&gt;&#xA;&lt;li&gt;Notify: parse the responses and send notification for any that fail&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;comparison&#34;&gt;Comparison&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, the Node package has quite a few layers to it (e.g. Dockerfile, package.json, dependencies, multiple nested files that take some time to navigate around) whereas my &amp;lsquo;Bash Watchtower&amp;rsquo; is a single shell script. So it&amp;rsquo;s actually a lot easier and quicker (in my opinion at least) to understand what&amp;rsquo;s going on and how things work.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;on the plus side, he&amp;rsquo;s got tests :-)&lt;br&gt;&#xA;I couldn&amp;rsquo;t be bothered with that for this quick hack&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;My initial concern was going to be around the performance of requesting multiple endpoints, as well as sending potentially multiple failure notifications to the remote service (Slack). I knew that Node is popular for its event driven concurrency, and I was keen to ensure performance wasn&amp;rsquo;t degraded in any way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;d argue (in theory, I haven&amp;rsquo;t actually tested) that performance would be equal or better because I&amp;rsquo;m running the relevant sections of the code in &lt;em&gt;parallel&lt;/em&gt; rather than &lt;em&gt;concurrently&lt;/em&gt; using the shell&amp;rsquo;s &lt;code&gt;&amp;amp;&lt;/code&gt; operator to &amp;lsquo;background&amp;rsquo; each request/notification into a separate subshell. I&amp;rsquo;m then utilising the &lt;code&gt;wait&lt;/code&gt; command which (as the name suggests) waits for all currently active child processes to complete.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because of the background processes, this script will not scale and be as performant once the number of URLs you&amp;rsquo;re looking to check against becomes very large. So if you&amp;rsquo;re looking to validate 100&amp;rsquo;s of URLs, then you&amp;rsquo;ll likely hit performance issues&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;code&#34;&gt;Code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So here is the code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function cleanup() {&#xA;  rm results.txt&#xA;  rm temp.txt&#xA;}&#xA;&#xA;function pull() {&#xA;  local base=$1&#xA;  local urls=(&amp;quot;${!2}&amp;quot;)&#xA;&#xA;  for resource in &amp;quot;${urls[@]}&amp;quot;&#xA;  do&#xA;    curl $base$resource --head \&#xA;                        --location \&#xA;                        --silent \&#xA;                        --output /dev/null \&#xA;                        --connect-timeout 2 \&#xA;                        --write-out &amp;quot;%{url_effective} %{http_code}\n&amp;quot; &amp;amp;&#xA;  done&#xA;&#xA;  wait&#xA;}&#xA;&#xA;function parse() {&#xA;  local results=$1&#xA;  local remote=https://hooks.slack.com/services/foo/bar/baz&#xA;&#xA;  cat $results | awk &#39;!/200/ { print $2 &amp;quot;: &amp;quot; $1 }&#39; &amp;gt; temp.txt&#xA;&#xA;  while read line; do&#xA;    curl --header &amp;quot;Content-Type: application/json&amp;quot; \&#xA;         --silent \&#xA;         --output /dev/null \&#xA;         --request POST \&#xA;         --data &amp;quot;{\&amp;quot;text\&amp;quot;: \&amp;quot;$line\&amp;quot;}&amp;quot; $remote &amp;amp;&#xA;  done &amp;lt; temp.txt&#xA;&#xA;  wait&#xA;&#xA;  display temp.txt&#xA;}&#xA;&#xA;function display() {&#xA;  printf &amp;quot;\n\n&amp;quot;&#xA;  cat $1&#xA;  printf &amp;quot;\n\n&amp;quot;&#xA;}&#xA;&#xA;trap cleanup EXIT&#xA;&#xA;endpoints=(&#xA;  /newsbeat&#xA;  /newsbeat/popular&#xA;  /newsbeat/topics&#xA;  /newsbeat/topics/entertainment&#xA;  /newsbeat/topics/surgery&#xA;  /newsbeat/article/32792353/im-engaged-but-will-i-ever-be-able-to-marry-my-boyfriend&#xA;)&#xA;&#xA;pull http://bbc.co.uk endpoints[@] &amp;gt; results.txt&#xA;display results.txt&#xA;parse results.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve multilined the &lt;code&gt;curl&lt;/code&gt; request here for readability (but I prefer one liners)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;explanation&#34;&gt;Explanation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The script is broken out into functions:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cleanup&lt;/code&gt;: removes specified files&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pull&lt;/code&gt;: gets our endpoints (only the HTTP headers)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;parse&lt;/code&gt;: looks for non-200 status code and sends notification&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;display&lt;/code&gt;: prints specified file&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;cleanup&lt;/code&gt; and &lt;code&gt;display&lt;/code&gt; functions aren&amp;rsquo;t of any special interest, so we&amp;rsquo;ll focus primarily on &lt;code&gt;pull&lt;/code&gt; and &lt;code&gt;parse&lt;/code&gt;. The only thing I will say is that previously I was manually calling &lt;code&gt;cleanup&lt;/code&gt; twice (the function was originally written to take an argument - a file path - and remove the specified file if it indeed existed); this has since changed to not take an argument but instead explictly remove the two files I know I create within this script.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I also now automatically run the &lt;code&gt;cleanup&lt;/code&gt; function when the shell exits. I do this using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;trap cleanup EXIT&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;ve not seen this before then please refer to &lt;code&gt;help trap&lt;/code&gt; for more details.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;most of the time the &lt;code&gt;man &amp;lt;command&amp;gt;&lt;/code&gt; will help you locate information&lt;br&gt;&#xA;But with builtin commands (those that are part of the shell environment itself)&lt;br&gt;&#xA;you need to use: &lt;code&gt;help &amp;lt;command&amp;gt;&lt;/code&gt; (e.g. &lt;code&gt;help trap&lt;/code&gt; or &lt;code&gt;help wait&lt;/code&gt;)&lt;br&gt;&#xA;Failing that you could search inside &lt;code&gt;man bash&lt;/code&gt; but that&amp;rsquo;s lunacy!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;pull&#34;&gt;Pull&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;First we take in two arguments, the first we store in a local variable called &lt;code&gt;base&lt;/code&gt; while the other is stored in a variable called &lt;code&gt;urls&lt;/code&gt;. You&amp;rsquo;ll notice we&amp;rsquo;ve had to convert the second argument into an Array by assigning something that resembles an Array (e.g. the parentheses &lt;code&gt;(...)&lt;/code&gt;) and then expand the incoming string of elements inside it (&lt;code&gt;(&amp;quot;${!2}&amp;quot;)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll notice that when we call &lt;code&gt;pull&lt;/code&gt;&lt;br&gt;&#xA;we have to pass &lt;code&gt;endpoints[@]&lt;/code&gt; and not &lt;code&gt;$endpoints&lt;/code&gt;&lt;br&gt;&#xA;this is to ensure we properly expand all elements within the Array&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next we loop over the &lt;code&gt;urls&lt;/code&gt; Array and for each item we send a &lt;code&gt;curl&lt;/code&gt; request (which in this case is a unique URL constructed from the &lt;code&gt;$base&lt;/code&gt; and &lt;code&gt;$resource&lt;/code&gt; variables), but we specify that we&amp;rsquo;re only interested in getting back the HTTP headers for the request (&lt;code&gt;--head&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We make sure that if the resource being requested actually &lt;code&gt;301&lt;/code&gt; redirects to another endpoint, then we should follow that redirect to the new location (&lt;code&gt;--location&lt;/code&gt;). We&amp;rsquo;re also not interested in any progress bars or error output (&lt;code&gt;--silent&lt;/code&gt;). We direct any other &amp;lsquo;output&amp;rsquo; to &lt;code&gt;/dev/null&lt;/code&gt;, as we don&amp;rsquo;t need it (&lt;code&gt;--output /dev/null&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After this we specify a timeout for each request, as we don&amp;rsquo;t want a slow server to impact our script&amp;rsquo;s performance (&lt;code&gt;--connect-timeout 2&lt;/code&gt;). Now we tell &lt;code&gt;curl&lt;/code&gt; to make sure after a successful request it should dump out some additional information to &lt;code&gt;stdout&lt;/code&gt; and that it should be formatted in a specific way (&lt;code&gt;--write-out &amp;quot;%{url_effective} %{http_code}&lt;/code&gt;) as this makes it easier for us to deal with (as outside of this function we redirect this &lt;code&gt;stdout&lt;/code&gt; information into a file called &lt;code&gt;result.txt&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally we call &lt;code&gt;wait&lt;/code&gt;, which as we now know (see above) will wait for each of the backgrounded child processes to complete before the function ends.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;parse&#34;&gt;Parse&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In this function we take in a single argument, the &lt;code&gt;results.txt&lt;/code&gt; file, which would contain a set of &amp;lsquo;results&amp;rsquo; that &lt;em&gt;could&lt;/em&gt; look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;http://www.bbc.co.uk/newsbeat/topics/entertainment 200&#xA;http://www.bbc.co.uk/newsbeat/popular 200&#xA;http://www.bbc.co.uk/newsbeat/topics 200&#xA;http://www.bbc.co.uk/newsbeat 200&#xA;http://www.bbc.co.uk/newsbeat/topics/surgery 200&#xA;http://www.bbc.co.uk/newsbeat/article/32792353/im-engaged-but-will-i-ever-be-able-to-marry-my-boyfriend 500&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;here the results suggest only one URL has returned a 500 status code&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We also store off our remote endpoint (in my case: our Slack incoming webhook URL) in a variable called &lt;code&gt;remote&lt;/code&gt;. This is where we&amp;rsquo;ll be sending our JSON data of failed URLs to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point we use &lt;a href=&#34;https://en.wikipedia.org/wiki/AWK&#34; target=&#34;_blank&#34;&gt;Awk&lt;/a&gt; to check each line of the incoming &lt;code&gt;results.txt&lt;/code&gt; to see if it doesn&amp;rsquo;t include &lt;code&gt;200&lt;/code&gt; somewhere. If it doesn&amp;rsquo;t then we store that line into a &lt;code&gt;temp.txt&lt;/code&gt; file in the format of &lt;code&gt;&amp;lt;status_code&amp;gt; &amp;lt;url&amp;gt;&lt;/code&gt;. We then redirect the contents of &lt;code&gt;temp.txt&lt;/code&gt; into a &lt;code&gt;while read&lt;/code&gt; loop and for each line we &lt;code&gt;curl&lt;/code&gt; our remote endpoint (in parallel using &lt;code&gt;&amp;amp;&lt;/code&gt;); POST&amp;rsquo;ing it a JSON object that details the URL that gave a non-200 response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, like the &lt;code&gt;pull&lt;/code&gt; function, we utilise &lt;code&gt;wait&lt;/code&gt; to ensure all the child subprocesses finish before doing some final displaying and cleanup of the &lt;code&gt;temp.txt&lt;/code&gt; file and then returning the function back to the caller.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it. Fairly standard Bash scripting. I&amp;rsquo;m sure they&amp;rsquo;ll be some unix/linux neck-beard wizards in the audience ready to &amp;lsquo;shred me a new one&amp;rsquo; because my chops aren&amp;rsquo;t as &lt;em&gt;wizardy&lt;/em&gt; as theirs. If that&amp;rsquo;s the case: feel free to get in contact as I&amp;rsquo;d love to know how I could make this code simpler or easier to work with (or just more idiomatic).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/bash-watchtower/</guid>
      <link>https://www.integralist.co.uk/posts/bash-watchtower/</link>
      <pubDate>Thu, 03 Mar 2016 00:00:00 +0000</pubDate>
      <title>Bash Watchtower</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s begin by understanding what an RPC (Remote Procedure Call) actually is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;RPC is a way of connecting two separate services via a raw TCP socket&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;outline&#34;&gt;Outline&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The fundamental principle behind RPC is to create a service that exposes a function behind that service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The steps typically look something like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write a function&lt;/li&gt;&#xA;&lt;li&gt;Add some RPC configuration&lt;/li&gt;&#xA;&lt;li&gt;Register our function as part of our RPC service&lt;/li&gt;&#xA;&lt;li&gt;Start the service and have it listen for messages on a specific port&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;From here we would need to have a client that calls the RPC service:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write code which calls RPC function&lt;/li&gt;&#xA;&lt;li&gt;Call the function via a TCP socket with a specific ip/port&lt;/li&gt;&#xA;&lt;li&gt;The resulting &amp;lsquo;message&amp;rsquo; can be passed back in different formats (e.g. JSON)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;variations&#34;&gt;Variations&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;With this understanding we can now start to look at the &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; programming language and the different variations of its RPC package(s) that it offers. Effectively they consist of behaviour such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;RPC over HTTP&lt;/li&gt;&#xA;&lt;li&gt;RPC over TCP&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The latter variation allows the use of either the standard &lt;code&gt;net/rpc&lt;/code&gt; package or a JSON formatted version found under &lt;code&gt;net/rpc/jsonrpc&lt;/code&gt;. In this post we&amp;rsquo;ll take a look at code examples for each of these packages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When utilising RPC you&amp;rsquo;ll typically find there are three &amp;lsquo;&lt;em&gt;parts&lt;/em&gt;&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Backend (the RPC function)&lt;/li&gt;&#xA;&lt;li&gt;Service (exposes the RPC)&lt;/li&gt;&#xA;&lt;li&gt;Client (calls the RPC)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;In most cases the backend will be unaffected. By this I mean, it&amp;rsquo;s just a package with a set of behaviours/functionality which are being remotely exposed. The actual use of the &lt;code&gt;net/rpc&lt;/code&gt; and &lt;code&gt;net/rpc/jsonrpc&lt;/code&gt; packages are typically used within the Service and Client packages †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† unless the client is implemented in another language,&lt;br&gt;&#xA;then you&amp;rsquo;ll use whatever is best suited to that language&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;requirements&#34;&gt;Requirements&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Only methods that satisfy the following criteria will be made available for remote access, all other methods will be ignored (so if you hit a problem in the below code, chances are you&amp;rsquo;re not exporting the expected items):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the method&amp;rsquo;s type is exported&lt;/li&gt;&#xA;&lt;li&gt;the method is exported&lt;/li&gt;&#xA;&lt;li&gt;the method has two arguments, both exported&lt;/li&gt;&#xA;&lt;li&gt;the method&amp;rsquo;s second argument is a pointer&lt;/li&gt;&#xA;&lt;li&gt;the method has return type error&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;rpc-over-http&#34;&gt;RPC over HTTP&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve yet to find a justification for using HTTP over TCP, but &lt;em&gt;you&lt;/em&gt; may have your reasons. If that&amp;rsquo;s the case, then here is an example of how to achieve this in Go.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First, here&amp;rsquo;s the directory structure I&amp;rsquo;m using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;├── remote&#xA;│   ├── rpc-html-backend.go&#xA;├── rpc-html-client.go&#xA;├── rpc-html-service.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-html-backend-go&#34;&gt;rpc-html-backend.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As mentioned earlier, the backends responsibility is to &lt;em&gt;define&lt;/em&gt; a specific function or behaviour (see the code comments for additional information):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package remote&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;// Args is a data structure for the incoming arguments&#xA;// This needs to be exported for the RPC to be valid/work&#xA;type Args struct {&#xA;  A, B int&#xA;}&#xA;&#xA;// Arith is our functions return type&#xA;// This also needs to be exported&#xA;type Arith int&#xA;&#xA;// Multiply does simply multiplication on provided arguments&#xA;// This also needs to be exported&#xA;func (t *Arith) Multiply(args *Args, reply *int) error {&#xA;  fmt.Printf(&amp;quot;Args received: %+v\n&amp;quot;, args)&#xA;  *reply = args.A * args.B&#xA;  return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-html-service-go&#34;&gt;rpc-html-service.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The service&amp;rsquo;s responsibility is to &lt;em&gt;expose&lt;/em&gt; the specific function. Below we do this using RPC over HTTP, so you&amp;rsquo;ll notice the use of &lt;code&gt;rpc.HandleHTTP&lt;/code&gt; for setting up a HTTP based handler and &lt;code&gt;http.Serve&lt;/code&gt; for serving back a response to the client:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;&#xA;  &amp;quot;github.com/integralist/rpc/remote&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  arith := new(remote.Arith)&#xA;&#xA;  rpc.Register(arith)&#xA;  rpc.HandleHTTP()&#xA;&#xA;  l, e := net.Listen(&amp;quot;tcp&amp;quot;, &amp;quot;:1234&amp;quot;)&#xA;  if e != nil {&#xA;    log.Fatal(&amp;quot;listen error:&amp;quot;, e)&#xA;  }&#xA;&#xA;  for {&#xA;    http.Serve(l, nil)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I was a little confused originally about having to manually open a TCP socket. I just assumed that in using HTTP, that step would&amp;rsquo;ve been abstracted away for me. But it&amp;rsquo;s not, oh well&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-html-client-go&#34;&gt;rpc-html-client.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The client&amp;rsquo;s responsibility is to connect to the remote service and call its exposed function. As our service is using RPC over HTTP you&amp;rsquo;ll notice our client uses &lt;code&gt;rpc.DialHTTP&lt;/code&gt; to create the TCP socket connection, just before calling the remote function via the returned client instance:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;)&#xA;&#xA;type args struct {&#xA;  A, B int&#xA;}&#xA;&#xA;func main() {&#xA;  client, err := rpc.DialHTTP(&amp;quot;tcp&amp;quot;, &amp;quot;localhost:1234&amp;quot;)&#xA;  if err != nil {&#xA;    log.Fatal(&amp;quot;dialing:&amp;quot;, err)&#xA;  }&#xA;&#xA;  var reply int&#xA;&#xA;  e := client.Call(&amp;quot;Arith.Multiply&amp;quot;, &amp;amp;args{4, 2}, &amp;amp;reply)&#xA;  if e != nil {&#xA;    log.Fatalf(&amp;quot;Something went wrong: %s&amp;quot;, err.Error())&#xA;  }&#xA;&#xA;  fmt.Printf(&amp;quot;The reply pointer value has been changed to: %d&amp;quot;, reply)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the following program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Args received: &amp;amp;{A:4 B:2}&#xA;The reply pointer value has been changed to: 8&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;rpc-over-tcp&#34;&gt;RPC over TCP&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most of the time when you&amp;rsquo;re exposing functionality and behaviour remotely, you&amp;rsquo;ll want to have the least amount of overhead as possible and so you&amp;rsquo;ll resort to stripping out the HTTP application layer and moving down to using just the TCP layer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First, here&amp;rsquo;s the directory structure I&amp;rsquo;m using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;├── remote&#xA;│   ├── rpc-tcp-backend.go&#xA;├── rpc-tcp-client.go&#xA;├── rpc-tcp-service.go&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-tcp-backend-go&#34;&gt;rpc-tcp-backend.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As before, the backend&amp;rsquo;s repsonsibility is to define a set of behaviours and functions (as mentioned above in the HTTP example, we need to export certain items in order for the RPC to be valid and work):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package remote&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;// TCPArgs is structured around the client&#39;s provided parameters&#xA;// The struct&#39;s fields need to be exported too!&#xA;type TCPArgs struct {&#xA;  Foo string&#xA;  Bar string&#xA;}&#xA;&#xA;// Compose is our RPC functions return type&#xA;type Compose string&#xA;&#xA;// Details is our exposed RPC function&#xA;func (c *Compose) Details(args *TCPArgs, reply *string) error {&#xA;  fmt.Printf(&amp;quot;Args received: %+v\n&amp;quot;, args)&#xA;  *c = &amp;quot;some value&amp;quot;&#xA;  *reply = &amp;quot;Blah!&amp;quot;&#xA;  return nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-tcp-service-go&#34;&gt;rpc-tcp-service.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Our service will now expose the above behaviour by using &lt;code&gt;rpc.Register&lt;/code&gt; along with &lt;code&gt;rpc.Accept&lt;/code&gt;. This is the simplest implementation possible. The call to &lt;code&gt;rpc.Accept&lt;/code&gt; is just a helper for directly accepting and serving an incoming request:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;&#xA;  &amp;quot;github.com/integralist/rpc/remote&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  compose := new(remote.Compose)&#xA;&#xA;  rpc.Register(compose)&#xA;&#xA;  listener, err := net.Listen(&amp;quot;tcp&amp;quot;, &amp;quot;:8080&amp;quot;)&#xA;  if err != nil {&#xA;    // handle error&#xA;  }&#xA;&#xA;  rpc.Accept(listener)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If on the other hand you wish to interrogate the request (or at the very least, execute some other behaviour in-between the request being accepted and it being served) you can change the code as follows to swap out &lt;code&gt;rpc.Accept&lt;/code&gt; for a &lt;code&gt;for&lt;/code&gt; loop which calls &lt;code&gt;Accept&lt;/code&gt; on the listener instance instead and then manually execute &lt;code&gt;rpc.ServeConn&lt;/code&gt; (but remember to do this via a goroutine because it&amp;rsquo;s a blocking call):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;&#xA;  &amp;quot;github.com/integralist/rpc/remote&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  compose := new(remote.Compose)&#xA;&#xA;  rpc.Register(compose)&#xA;&#xA;  listener, err := net.Listen(&amp;quot;tcp&amp;quot;, &amp;quot;:8080&amp;quot;)&#xA;  if err != nil {&#xA;    // handle error&#xA;  }&#xA;&#xA;  for {&#xA;    conn, err := listener.Accept()&#xA;    if err != nil {&#xA;      // handle error&#xA;    }&#xA;&#xA;    go rpc.ServeConn(conn)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;rpc-tcp-client-go&#34;&gt;rpc-tcp-client.go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Lastly, as we already know, the client&amp;rsquo;s responsibility is to call the exposed function. This time we use the &lt;code&gt;rpc.Dial&lt;/code&gt; function instead of &lt;code&gt;rpc.DialHTTP&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;)&#xA;&#xA;type args struct {&#xA;  Foo, Bar string&#xA;}&#xA;&#xA;func main() {&#xA;  client, err := rpc.Dial(&amp;quot;tcp&amp;quot;, &amp;quot;localhost:8080&amp;quot;)&#xA;  if err != nil {&#xA;    log.Fatal(&amp;quot;dialing:&amp;quot;, err)&#xA;  }&#xA;&#xA;  var reply string&#xA;&#xA;  e := client.Call(&amp;quot;Compose.Details&amp;quot;, &amp;amp;args{&amp;quot;Foo!&amp;quot;, &amp;quot;Bar!&amp;quot;}, &amp;amp;reply)&#xA;  if e != nil {&#xA;    log.Fatalf(&amp;quot;Something went wrong: %v&amp;quot;, e.Error())&#xA;  }&#xA;&#xA;  fmt.Printf(&amp;quot;The &#39;reply&#39; pointer value has been changed to: %s&amp;quot;, reply)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But if you want to implement a timeout (to prevent a call from taking too long), then you&amp;rsquo;ll want to change &lt;code&gt;rpc.Dial&lt;/code&gt; for &lt;code&gt;net.DialTimeout&lt;/code&gt; (notice they&amp;rsquo;re separate packages: &lt;code&gt;rpc&lt;/code&gt; vs &lt;code&gt;net&lt;/code&gt;). Also be aware that the returned type isn&amp;rsquo;t a client any more (as it is in the previous example); instead it is a &amp;lsquo;connection&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have the connection you can then pass that to &lt;code&gt;rpc.NewClient&lt;/code&gt;. Once you have your &amp;lsquo;client&amp;rsquo; you&amp;rsquo;ll notice that the rest of the code is the same as before (i.e. the calling of the exposed function via the client):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net&amp;quot;&#xA;  &amp;quot;net/rpc&amp;quot;&#xA;  &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;type args struct {&#xA;  Foo, Bar string&#xA;}&#xA;&#xA;func main() {&#xA;  conn, err := net.DialTimeout(&amp;quot;tcp&amp;quot;, &amp;quot;localhost:8080&amp;quot;, time.Minute)&#xA;  if err != nil {&#xA;    log.Fatal(&amp;quot;dialing:&amp;quot;, err)&#xA;  }&#xA;&#xA;  client := rpc.NewClient(conn)&#xA;&#xA;  var reply string&#xA;&#xA;  e := client.Call(&amp;quot;Compose.Details&amp;quot;, &amp;amp;args{&amp;quot;Foo!&amp;quot;, &amp;quot;Bar!&amp;quot;}, &amp;amp;reply)&#xA;  if e != nil {&#xA;    log.Fatalf(&amp;quot;Something went wrong: %v&amp;quot;, e.Error())&#xA;  }&#xA;&#xA;  fmt.Printf(&amp;quot;The &#39;reply&#39; pointer value has been changed to: %s&amp;quot;, reply)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the following program is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Args received: &amp;amp;{Foo:Foo! Bar:Bar!}&#xA;The &#39;reply&#39; pointer value has been changed to: Blah!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;json&#34;&gt;JSON&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There is another option available when creating an RPC and that is to expose a JSON formatted variation (which is &lt;em&gt;required&lt;/em&gt;† if you&amp;rsquo;re planning on using a different programming language to communicate with your Go RPC service - as we&amp;rsquo;ll see below when we write a client using the Ruby programming language).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† The standard net/rpc package uses &lt;a href=&#34;https://golang.org/pkg/encoding/gob/&#34; target=&#34;_blank&#34;&gt;https://golang.org/pkg/encoding/gob/&lt;/a&gt;&#xA;Which is a Go specific streaming binary format&lt;br&gt;&#xA;If your client isn&amp;rsquo;t Go then it&amp;rsquo;ll have a hard time communicating&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If we look back at our TCP example from earlier (the one which utilised &lt;code&gt;rpc.ServeConn&lt;/code&gt;), we can switch that over to being JSON formatted by just using the same code but making some minor changes:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In both the service and the client: swap &lt;code&gt;net/rpc&lt;/code&gt; to &lt;code&gt;net/rpc/jsonrpc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;In the service: swap &lt;code&gt;rpc.ServeConn&lt;/code&gt; to &lt;code&gt;jsonrpc.ServeConn&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;In the client: swap &lt;code&gt;rpc.Dial&lt;/code&gt; to &lt;code&gt;jsonrpc.Dial&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;calling-from-ruby&#34;&gt;Calling from Ruby&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you want to utilise a client written in another programming language (such as Ruby), you&amp;rsquo;ll need to have the Go service setup to use &lt;code&gt;net/rpc/jsonrpc&lt;/code&gt;. Once that&amp;rsquo;s done, your client can connect via a raw TCP socket and pass over JSON data, as shown in the below example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;require &amp;quot;socket&amp;quot;&#xA;require &amp;quot;json&amp;quot;&#xA;&#xA;socket = TCPSocket.new &amp;quot;localhost&amp;quot;, &amp;quot;8080&amp;quot;&#xA;&#xA;# Details of JSON structure can be found here:&#xA;# https://golang.org/src/net/rpc/jsonrpc/client.go#L45&#xA;# Thanks to Albert Hafvenström (@albhaf) for his help&#xA;b = {&#xA;  :method =&amp;gt; &amp;quot;Compose.Details&amp;quot;,&#xA;  :params =&amp;gt; [{ :Foo =&amp;gt; &amp;quot;Foo!&amp;quot;, :Bar =&amp;gt; &amp;quot;Bar!&amp;quot; }],&#xA;  :id     =&amp;gt; &amp;quot;0&amp;quot; # id is just echo&#39;ed back to the client&#xA;}&#xA;&#xA;socket.write(JSON.dump(b))&#xA;&#xA;p JSON.load(socket.readline)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output from this program would be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&amp;quot;id&amp;quot;=&amp;gt;&amp;quot;0&amp;quot;, &amp;quot;result&amp;quot;=&amp;gt;&amp;quot;Blah!&amp;quot;, &amp;quot;error&amp;quot;=&amp;gt;nil}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;grpc&#34;&gt;gRPC&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Google has started work on a new package called gRPC which, as per the site: &lt;a href=&#34;http://www.grpc.io/&#34; target=&#34;_blank&#34;&gt;grpc.io&lt;/a&gt;, states&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;is a high performance, open source, general RPC framework that puts mobile and HTTP/2 first&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;They currently support C++, Java, Objective-C, Python, Ruby, Go, C#, Node.js, and PHP. You can either go to the main GitHub repo (&lt;a href=&#34;https://github.com/grpc&#34; target=&#34;_blank&#34;&gt;github.com/grpc&lt;/a&gt;) or if you&amp;rsquo;re only interested in the Go version, then you can find it here: &lt;a href=&#34;https://github.com/grpc/grpc-go&#34; target=&#34;_blank&#34;&gt;github.com/grpc/grpc-go&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve not tried it yet, but it looks interesting.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;update&#34;&gt;Update&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve setup gRPC now. You can find a beginners guide I&amp;rsquo;ve written &lt;a href=&#34;/posts/grpc-for-beginners/&#34;&gt;here&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/rpc-variations-in-go/</guid>
      <link>https://www.integralist.co.uk/posts/rpc-variations-in-go/</link>
      <pubDate>Fri, 19 Feb 2016 00:00:00 +0000</pubDate>
      <title>RPC Variations in Go</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is some code that demonstrates the typical &amp;lsquo;hello world&amp;rsquo; for a Go based web server:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;func handler(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;Hello %s&amp;quot;, r.URL.Path[1:])&#xA;}&#xA;&#xA;func main() {&#xA;  http.HandleFunc(&amp;quot;/World&amp;quot;, handler)&#xA;  http.ListenAndServe(&amp;quot;:8080&amp;quot;, nil)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;http://localhost:8080/World&lt;/code&gt; will return &lt;code&gt;Hello World&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;For most people, setting up a web server to handle incoming HTTP requests is considered a quick and simple introduction to the &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go programming language&lt;/a&gt;, and looking at the above code it&amp;rsquo;s easy to see why that would be the case. But further investigation can yield some nice learnings about Go&amp;rsquo;s built-in &lt;code&gt;func&lt;/code&gt; type and how it is used as an adapter layer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this blog post I will demonstrate a few different ways of creating a web server and then I&amp;rsquo;ll clarify how some of the functionality (specifically &lt;code&gt;http.HandleFunc&lt;/code&gt;) works. What initially drove me to look into this was my curiosity as to why I would always insert &lt;code&gt;nil&lt;/code&gt; to the &lt;code&gt;http.ListenAndServe&lt;/code&gt; function by default when setting up a basic web server (see above code example).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It was never really that clear to me and so it&amp;rsquo;s just something I &amp;lsquo;cargo cult&amp;rsquo;ed and subsequently replicated every single time I needed a web server. I realised I needed to know what its purpose was in order to feel like I wasn&amp;rsquo;t going through the motions unnecessarily or missing out on additional functionality (which it turns out I was).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;four-ways-to-skin-a-cat&#34;&gt;Four ways to skin a cat&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are currently four ways, that I know of, to create a web server with Go (well, actually only three - the first two examples are effectively the same - but we add a little more code to demonstrate different ways incoming requests can be handled).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each of the variations ultimately revolve around what we send to &lt;code&gt;http.ListenAndServe&lt;/code&gt; as its second argument (and this &amp;lsquo;thing&amp;rsquo; we send also ultimately should have a &lt;code&gt;ServeHTTP&lt;/code&gt; method; we&amp;rsquo;ll see shortly how this is achieved in different ways).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So here are each of the variations:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;No request parsing (serve same content regardless of request)&lt;/li&gt;&#xA;&lt;li&gt;Manual request parsing&lt;/li&gt;&#xA;&lt;li&gt;Multiplexer&lt;/li&gt;&#xA;&lt;li&gt;Global multiplexer&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;no-request-parsing&#34;&gt;No request parsing&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The most basic implementation (and by basic I don&amp;rsquo;t mean &amp;lsquo;simplest&amp;rsquo;, more&amp;hellip; &amp;lsquo;raw&amp;rsquo;) is demonstrated in the below code sample, which calls &lt;code&gt;ListenAndServe&lt;/code&gt; and passes in &lt;code&gt;db&lt;/code&gt; as its second argument.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although I wrote this blog post back in October 2015, I&amp;rsquo;ve rewritten the below examples based off inspiration from &amp;ldquo;The Go Programming&amp;rdquo; book I&amp;rsquo;ve been reading recently&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This first section will give us enough background and grounding to build upon in the latter sections:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type pounds float32&#xA;&#xA;func (p pounds) String() string {&#xA;  return fmt.Sprintf(&amp;quot;£%.2f&amp;quot;, p)&#xA;}&#xA;&#xA;type database map[string]pounds&#xA;&#xA;func (d database) ServeHTTP(w http.ResponseWriter, r *http.Request) {&#xA;  for item, price := range d {&#xA;    fmt.Fprintf(w, &amp;quot;%s: %s\n&amp;quot;, item, price)&#xA;  }&#xA;}&#xA;&#xA;func main() {&#xA;  db := database{&#xA;    &amp;quot;foo&amp;quot;: 1,&#xA;    &amp;quot;bar&amp;quot;: 2,&#xA;  }&#xA;&#xA;  log.Fatal(http.ListenAndServe(&amp;quot;localhost:8000&amp;quot;, db))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see from the above code sample that &lt;code&gt;db&lt;/code&gt; is an instance of our custom &lt;code&gt;database&lt;/code&gt; type, which states it should be a map data structure consisting of strings for keys and &lt;code&gt;pounds&lt;/code&gt; for values.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can also see that &lt;code&gt;pounds&lt;/code&gt; is itself a type of &lt;code&gt;float32&lt;/code&gt; and has a custom &lt;code&gt;String&lt;/code&gt; method attached, allowing us to modify its output when converted into a string value. Similarly the &lt;code&gt;database&lt;/code&gt; type has a method attached, but this time it is a &lt;code&gt;ServeHTTP&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ServeHTTP&lt;/code&gt; is required in order to satisfy the &lt;code&gt;ListenAndServe&lt;/code&gt; method signature, which states the second argument should be a type of &lt;code&gt;Handler&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func ListenAndServe(addr string, handler Handler) error&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;godoc net/http ListenAndServe | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If we look at the source code for the &lt;code&gt;Handler&lt;/code&gt; type (below) we can clearly see it requires a &lt;code&gt;ServeHTTP&lt;/code&gt; method to be available (hence why our &lt;code&gt;database&lt;/code&gt; type associates its own &lt;code&gt;ServeHTTP&lt;/code&gt; method):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Handler interface {&#xA;    ServeHTTP(ResponseWriter, *Request)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;godoc net/http Handler | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The above sample web server code will always serve the same response regardless of the URL that was specified. So for example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http://localhost:8000/&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;http://localhost:8000/abc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;http://localhost:8000/xyz&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;will all serve back the response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo: £1.00&#xA;bar: £2.00&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;manual-request-parsing&#34;&gt;Manual request parsing&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, so now we&amp;rsquo;ve got the above example written. Let&amp;rsquo;s enhance it by allowing our application to handle different routes as apposed to serving the same content all the time. To do this we&amp;rsquo;ll modify our &lt;code&gt;ServeHTTP&lt;/code&gt; method to interrogate the incoming request object and parse out the URL, as demonstrated in the below code sample:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type pounds float32&#xA;&#xA;func (p pounds) String() string {&#xA;  return fmt.Sprintf(&amp;quot;£%.2f&amp;quot;, p)&#xA;}&#xA;&#xA;type database map[string]pounds&#xA;&#xA;func (d database) ServeHTTP(w http.ResponseWriter, r *http.Request) {&#xA;  switch r.URL.Path {&#xA;  case &amp;quot;/foo&amp;quot;:&#xA;    fmt.Fprintf(w, &amp;quot;foo: %s\n&amp;quot;, d[&amp;quot;foo&amp;quot;])&#xA;  case &amp;quot;/bar&amp;quot;:&#xA;    fmt.Fprintf(w, &amp;quot;bar: %s\n&amp;quot;, d[&amp;quot;bar&amp;quot;])&#xA;  default:&#xA;    w.WriteHeader(http.StatusNotFound)&#xA;    fmt.Fprintf(w, &amp;quot;No page found for: %s\n&amp;quot;, r.URL)&#xA;  }&#xA;}&#xA;&#xA;func main() {&#xA;  db := database{&#xA;    &amp;quot;foo&amp;quot;: 1,&#xA;    &amp;quot;bar&amp;quot;: 2,&#xA;  }&#xA;&#xA;  log.Fatal(http.ListenAndServe(&amp;quot;localhost:8000&amp;quot;, db))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Nothing else to say about this, other than we&amp;rsquo;ve implemented what we set out to do by utilising a simple &lt;code&gt;switch&lt;/code&gt; statement that checks for known paths and writes to the &lt;code&gt;http.ResponseWriter&lt;/code&gt; a different response depending on the request. If we can&amp;rsquo;t match the URL then we&amp;rsquo;ll instead send a &lt;code&gt;404&lt;/code&gt; status code (&lt;code&gt;StatusNotFound&lt;/code&gt;) followed by a message to notify the user we couldn&amp;rsquo;t identify their request.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;godoc -src net/http WriteHeader | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;multiplexer&#34;&gt;Multiplexer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So writing the above example demonstrates a bit of a code smell. We could extract each case&amp;rsquo;s block into separate functions but it&amp;rsquo;s still an ever growing switch statement. We&amp;rsquo;re also confined to using objects that implement the required interface (e.g. if you don&amp;rsquo;t provide an object that has a &lt;code&gt;ServeHTTP&lt;/code&gt; method then you&amp;rsquo;re not going to have much success).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead it would be nice if you could just pick an arbitrary function and allow it to be used as a handler. That&amp;rsquo;s exactly what &lt;code&gt;ServeMux&lt;/code&gt; provides to us via its &lt;code&gt;HandleFunc&lt;/code&gt; function (which is really just a convenience method on top of &lt;code&gt;http.HandlerFunc&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;godoc net/http ServeMux | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The following code sample demonstrates this in action, by removing the &lt;code&gt;ServeHTTP&lt;/code&gt; method from the &lt;code&gt;database&lt;/code&gt; type and instead implementing individual methods for our defined routes to call.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type pounds float32&#xA;&#xA;func (p pounds) String() string {&#xA;  return fmt.Sprintf(&amp;quot;£%.2f&amp;quot;, p)&#xA;}&#xA;&#xA;type database map[string]pounds&#xA;&#xA;func (d database) foo(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;foo: %s\n&amp;quot;, d[&amp;quot;foo&amp;quot;])&#xA;}&#xA;&#xA;func (d database) bar(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;bar: %s\n&amp;quot;, d[&amp;quot;bar&amp;quot;])&#xA;}&#xA;&#xA;func (d database) baz(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;baz: %s\n&amp;quot;, d[&amp;quot;baz&amp;quot;])&#xA;}&#xA;&#xA;func main() {&#xA;  db := database{&#xA;    &amp;quot;foo&amp;quot;: 1,&#xA;    &amp;quot;bar&amp;quot;: 2,&#xA;    &amp;quot;baz&amp;quot;: 3,&#xA;  }&#xA;&#xA;  mux := http.NewServeMux()&#xA;&#xA;  mux.Handle(&amp;quot;/foo&amp;quot;, http.HandlerFunc(db.foo))&#xA;  mux.Handle(&amp;quot;/bar&amp;quot;, http.HandlerFunc(db.bar))&#xA;&#xA;  // Convenience method for longer form mux.Handle&#xA;  mux.HandleFunc(&amp;quot;/baz&amp;quot;, db.baz)&#xA;&#xA;  log.Fatal(http.ListenAndServe(&amp;quot;localhost:8000&amp;quot;, mux))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As we can see, we create a new &lt;code&gt;ServeMux&lt;/code&gt; instance using &lt;code&gt;http.NewServeMux&lt;/code&gt; and then register our &lt;code&gt;database&lt;/code&gt; methods as handlers for each of the route&amp;rsquo;s we want to match them against. The &lt;code&gt;ServeMux&lt;/code&gt; instance is a multiplexer, meaning we can pass it as the second argument to &lt;code&gt;http.ListenAndServe&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can also see we demonstrate the shorthand &lt;code&gt;mux.HandleFunc&lt;/code&gt; which is really a convenience method over both &lt;code&gt;mux.Handle&lt;/code&gt; and &lt;code&gt;http.HandlerFunc&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So how does &lt;code&gt;http.HandlerFunc&lt;/code&gt; and &lt;code&gt;mux.HandleFunc&lt;/code&gt; allow us to use an arbitrary function (as none of those database functions have access to a &lt;code&gt;ServeHTTP&lt;/code&gt; function as required by &lt;code&gt;ListenAndServe&lt;/code&gt;)? We&amp;rsquo;ll come back to the answer in a little bit. Let&amp;rsquo;s quickly review the last variation of how to run a web server first&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;global-multiplexer&#34;&gt;Global multiplexer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Typically you&amp;rsquo;ll have your code split up into separate packages. So in order to setup your routing handlers, you would need to pass around your &lt;code&gt;ServeMux&lt;/code&gt; instance to each of these packages. Instead, you can just utilise Go&amp;rsquo;s global &lt;code&gt;DefaultServeMux&lt;/code&gt;. To do that you pass &lt;code&gt;nil&lt;/code&gt; as the second argument to &lt;code&gt;http.ListenAndServe&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Documentation: &lt;code&gt;godoc -src net/http DefaultServeMux | less&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The following code sample demonstrates this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;type pounds float32&#xA;&#xA;func (p pounds) String() string {&#xA;  return fmt.Sprintf(&amp;quot;£%.2f&amp;quot;, p)&#xA;}&#xA;&#xA;type database map[string]pounds&#xA;&#xA;func (d database) foo(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;foo: %s\n&amp;quot;, d[&amp;quot;foo&amp;quot;])&#xA;}&#xA;&#xA;func (d database) bar(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;bar: %s\n&amp;quot;, d[&amp;quot;bar&amp;quot;])&#xA;}&#xA;&#xA;func (d database) baz(w http.ResponseWriter, r *http.Request) {&#xA;  fmt.Fprintf(w, &amp;quot;baz: %s\n&amp;quot;, d[&amp;quot;baz&amp;quot;])&#xA;}&#xA;&#xA;func main() {&#xA;  db := database{&#xA;    &amp;quot;foo&amp;quot;: 1,&#xA;    &amp;quot;bar&amp;quot;: 2,&#xA;    &amp;quot;baz&amp;quot;: 3,&#xA;  }&#xA;&#xA;  http.HandleFunc(&amp;quot;/foo&amp;quot;, db.foo)&#xA;  http.HandleFunc(&amp;quot;/bar&amp;quot;, db.bar)&#xA;  http.HandleFunc(&amp;quot;/baz&amp;quot;, db.baz)&#xA;&#xA;  log.Fatal(http.ListenAndServe(&amp;quot;localhost:8000&amp;quot;, nil))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, we have a convenience method &lt;code&gt;HandleFunc&lt;/code&gt; which allows an arbitrary function to be adapted so it fits the interface requirements that &lt;code&gt;ListenAndServe&lt;/code&gt;&amp;rsquo;s second argument enforces.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-does-the-adapter-work&#34;&gt;How does the adapter work?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;adapter&amp;rsquo; here being the &lt;code&gt;http.HandleFunc&lt;/code&gt; function. How does it take an arbitrary function and enable it to support the relevant interface so it can be passed to &lt;code&gt;ListenAndServe&lt;/code&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way &lt;code&gt;http.HandleFunc&lt;/code&gt; solves this requirement is by internally calling its &lt;em&gt;other&lt;/em&gt; function &lt;code&gt;http.Handle&lt;/code&gt;, and passing it the required type (i.e. it passes a type that satisfies the interface requirement that the &lt;code&gt;Handle&lt;/code&gt; function has).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, let&amp;rsquo;s look back at the two functions and their respective signatures to refresh our memory as to what&amp;rsquo;s required:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;func Handle(pattern string, handler Handler)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;func HandleFunc(pattern string, handler func(ResponseWriter, *Request))&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;We can see the &lt;code&gt;Handle&lt;/code&gt; signature requires a type that satisfies the &lt;code&gt;Handler&lt;/code&gt; interface (which is defined as follows):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Handler interface {&#xA;  ServeHTTP(ResponseWriter, *Request)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In other words, as long as you pass in a type that has a &lt;code&gt;ServeHTTP&lt;/code&gt; method then the &lt;code&gt;Handle&lt;/code&gt; function will be happy. So &lt;code&gt;HandleFunc&lt;/code&gt; facilitates this requirement by taking your user defined function and converting it into a type that happens to have &lt;code&gt;ServeHTTP&lt;/code&gt; available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how does it do that conversion? Firstly it defines a &lt;code&gt;func&lt;/code&gt; type called &lt;code&gt;http.HandlerFunc&lt;/code&gt;, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type HandlerFunc func(ResponseWriter, *Request)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This says that for a function to match this type it should have the same signature (e.g. &lt;code&gt;ResponseWriter, *Request&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Inside the &lt;code&gt;HandleFunc&lt;/code&gt; function you&amp;rsquo;ll see it actually &lt;em&gt;calls&lt;/em&gt; this &lt;code&gt;func&lt;/code&gt; type and passes it your user defined function. This will look something like the following in the Go implementation source code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {&#xA;  mux.Handle(pattern, HandlerFunc(handler))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the call of &lt;code&gt;HandlerFunc(handler)&lt;/code&gt; (where &lt;code&gt;handler&lt;/code&gt; is your user defined function you passed into &lt;code&gt;HandleFunc&lt;/code&gt; from your application code). This is the &lt;em&gt;conversion&lt;/em&gt; of your function into the &lt;code&gt;HandlerFunc&lt;/code&gt; type. You&amp;rsquo;re now effectively passing a &lt;code&gt;HandlerFunc&lt;/code&gt; into the internal function &lt;code&gt;mux.Handle&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how does that help us? How does passing in a function that &lt;em&gt;looks&lt;/em&gt; like a &lt;code&gt;HandlerFunc&lt;/code&gt; type into &lt;code&gt;mux.Handle&lt;/code&gt; help us solve the problem that we&amp;rsquo;re still passing in a function that has no &lt;code&gt;ServeHTTP&lt;/code&gt; method available (and so should fail the interface requirement that &lt;code&gt;mux.Handle&lt;/code&gt; has)?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, once you convert your user defined function into a &lt;code&gt;HandlerFunc&lt;/code&gt; you&amp;rsquo;ll find it now &lt;em&gt;does&lt;/em&gt; have a &lt;code&gt;ServeHTTP&lt;/code&gt; method available. If we look at the Go source code, just after the definition of the &lt;code&gt;HandlerFunc&lt;/code&gt; func type, you&amp;rsquo;ll also find the following snippet of code:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {&#xA;  f(w, r)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This associates the required &lt;code&gt;ServeHTTP&lt;/code&gt; function with the &lt;code&gt;HandlerFunc&lt;/code&gt; type. So when you convert your function to a &lt;code&gt;HandlerFunc&lt;/code&gt; it will indeed gain access to a &lt;code&gt;ServeHTTP&lt;/code&gt; function!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also remember that when you associate a method with a type/object the receiver is also available to you. So in this case we can see the &lt;code&gt;f&lt;/code&gt; is actually your user defined function you passed in to be converted. So when you convert that user defined function into a &lt;code&gt;HandlerFunc&lt;/code&gt; you get the &lt;code&gt;ServeHTTP&lt;/code&gt; method which internally is calling your original user defined function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now take a quick look at that &lt;code&gt;mux.Handle&lt;/code&gt; function to see what it expects:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func (mux *ServeMux) Handle(pattern string, handler Handler) {&#xA;  ...&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As we can see it expects a type of &lt;code&gt;Handler&lt;/code&gt; to be provided. What is &lt;code&gt;Handler&lt;/code&gt;? Well remember from earlier this is an interface which states there should be a &lt;code&gt;ServeHTTP&lt;/code&gt; function available:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Handler interface {&#xA;  ServeHTTP(ResponseWriter, *Request)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We know now that we&amp;rsquo;ve utilised Go&amp;rsquo;s &lt;code&gt;func&lt;/code&gt; type to adapt/transform our incoming function into a type that has the required method &lt;code&gt;ServeHTTP&lt;/code&gt; associated with it, thus allowing it to pass the &lt;code&gt;Handler&lt;/code&gt; interface requirement.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-is-this-interesting&#34;&gt;Why is this interesting?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Really understanding what initially looked to be a simple web server abstraction ended up being a complex mix of types and interfaces that work together to allow seemingly incompatible types to be adapted to fit. Demonstrating how flexible and dynamic your code can be when working in an idiomatic way with the Go principles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I now have a much better appreciation of why lots of long time Gophers will routinely recommend sifting through the official Go source code, as it can indeed be quite enlightening.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;summary-breakdown&#34;&gt;Summary/Breakdown&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is a useful summary for you&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http.Handler&lt;/code&gt; = interface&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;you support &lt;code&gt;http.Handler&lt;/code&gt; if you have a &lt;code&gt;ServeHTTP(w http.ResponseWriter, r *http.Request)&lt;/code&gt; method available.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http.Handle(&amp;quot;/&amp;quot;, &amp;lt;give me something that supports the http.Handler interface&amp;gt;)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;e.g. an object with a &lt;code&gt;ServeHTTP&lt;/code&gt; method.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http.HandleFunc(&amp;quot;/&amp;quot;, &amp;lt;give me any function with the same signature as ServeHTTP &amp;gt;)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;e.g. a function that accepts the arguments &lt;code&gt;(w http.ResponseWriter, r *http.Request)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http.HandlerFunc&lt;/code&gt; = func type used internally by &lt;code&gt;http.HandleFunc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;e.g. it adapts the given function to the &lt;code&gt;http.HandlerFunc&lt;/code&gt; type, which has an associated &lt;code&gt;ServeHTTP&lt;/code&gt; method (that is able to call your original incompatible function).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/go-func-type/</guid>
      <link>https://www.integralist.co.uk/posts/go-func-type/</link>
      <pubDate>Mon, 23 Nov 2015 00:00:00 +0000</pubDate>
      <title>Understanding Golang&#39;s Func Type</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I recently had an issue with my GitHub set-up which has since prompted me to write this post. The issue I had was dealing with multiple GitHub accounts via SSH on a single laptop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I have a GitHub account under the username &lt;a href=&#34;https://github.com/Integralist&#34; target=&#34;_blank&#34;&gt;Integralist&lt;/a&gt;. This is a personal account, and up until recently I was also using it to access my work&amp;rsquo;s private repos (&lt;a href=&#34;https://github.com/bbc&#34; target=&#34;_blank&#34;&gt;BBC&lt;/a&gt; and &lt;a href=&#34;https://github.com/BBC-News&#34; target=&#34;_blank&#34;&gt;BBC-News&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When cloning a repo from GitHub you will typically create an &lt;a href=&#34;/posts/security-basics/#creating-your-own-keys&#34;&gt;SSH Key Pair&lt;/a&gt; and paste the contents of the public key into your GitHub account via their web site. When you come to clone a repo you&amp;rsquo;ll also typically use the SSH variation of the path:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git@github.com:Integralist/Go-Requester.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The problem occurred when I had to remove my personal account from the BBC/BBC-News repos and replace them with a generic &lt;a href=&#34;https://github.com/BBCMarkMcDonnell&#34; target=&#34;_blank&#34;&gt;BBCMarkMcDonnell&lt;/a&gt; account.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;The Problem?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So the first thing I did was create myself a new SSH Key, upload the public key to my new GitHub account.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I then added the private key to my laptop&amp;rsquo;s SSH-Agent:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssh-add -K ~/.ssh/github_bbc_rsa&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I then tried to clone one of the BBC&amp;rsquo;s private repos. This is where I discovered I didn&amp;rsquo;t have authorisation to clone the private repo.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It turns out that although I had both SSH Key Pairs loaded within my SSH-Agent&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssh-add -l&#xA; &#xA;# Returns something like...&#xA;#&#xA;# 4096 SHA256:xxxx /Users/M/.ssh/github_rsa (RSA)&#xA;# 4096 SHA256:xxxx /Users/M/.ssh/github_bbc_rsa (RSA)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;it was using the first key it came across for the host &lt;code&gt;github.com&lt;/code&gt;, so it used my personal account to try and access the private BBC repositories (which obviously it&amp;rsquo;s no longer authorised to do).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a problem because I have two separate keys for the same host, and I work on both BBC and personal code from my work laptop; so I needed to figure out how to get around this issue.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-solution&#34;&gt;The Solution&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The solution turned out to be pretty straight forward, if not immediately obvious. I would need to modify my &lt;code&gt;~/.ssh/config&lt;/code&gt; file (you&amp;rsquo;ll need to create that file if you don&amp;rsquo;t already have one).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then when cloning a private BBC repo I simply modify the clone command slightly. So where I would normally use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git clone git@github.com:bbc/mozart.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I would now use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git clone git@BBCMarkMcDonnell:bbc/mozart.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s take a look at how&amp;rsquo;s this is done.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;creating-a-new-key&#34;&gt;Creating a new Key&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First things first, create a new SSH Key Pair and name it something relevant (e.g. I used &lt;code&gt;github_bbc_rsa&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C &amp;quot;you@example.com&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Next, paste the public key part into your GitHub account and add the private key to your SSH-Agent:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;eval &amp;quot;$(ssh-agent -s)&amp;quot;&#xA;ssh-add -K ~/.ssh/github_bbc_rsa&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;ssh-add -l&lt;/code&gt; will show you what keys have been added to the agent&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;ssh-config&#34;&gt;SSH Config&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now create the file &lt;code&gt;~/.ssh/config&lt;/code&gt; (or modify the existing one you have):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Host BBCMarkMcDonnell&#xA;  User git&#xA;  HostName github.com&#xA;  IdentityFile ~/.ssh/github_bbc_rsa&#xA;&#xA;Host Integralist&#xA;  User git&#xA;  HostName github.com&#xA;  IdentityFile ~/.ssh/github_rsa&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see I&amp;rsquo;ve created two hosts:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;BBCMarkMcDonnell&lt;/li&gt;&#xA;&lt;li&gt;Integralist&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can call them whatever you like, I opted for the username for each account&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The keys within these two hosts are exactly the same. They state for the user &lt;code&gt;git&lt;/code&gt;, and the hostname &lt;code&gt;github.com&lt;/code&gt; make sure you use the specified &lt;code&gt;IdentityFile&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if I want to access the BBC private repos then I&amp;rsquo;ll use the following modified &lt;code&gt;git clone&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git clone git@BBCMarkMcDonnell:bbc/mozart.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where you can see the host section (&lt;code&gt;github.com&lt;/code&gt;) has been replaced with &lt;code&gt;BBCMarkMcDonnell&lt;/code&gt; which maps to the host block defined inside my &lt;code&gt;~/.ssh/config&lt;/code&gt; file. So it&amp;rsquo;ll use the relevant identity file needed to authorise successfully with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the second &lt;code&gt;Host&lt;/code&gt; (Integralist) is actually redundant for my use case because if I want to clone one of my own repos (which are all public) then I&amp;rsquo;d execute something like &lt;code&gt;git@github.com:Integralist/Go-Requester.git&lt;/code&gt; (this being the same command I&amp;rsquo;ve always run; no modification to it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What happens is SSH-Agent will do what it did before, which is look through the list of signatures within the SSH Agent and pick the first one that matches, which happens to be my personal Integralist account any way. But it works either way, I can either leave it up to the SSH Agent to locate my personal account or I could explicitly specify it like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git@Integralist:Integralist/Go-Requester.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;optional-shell-function&#34;&gt;Optional Shell Function&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The last thing I did was to create a quick shell function that allowed me to update my global git settings. By default they&amp;rsquo;re set to the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global user.name &amp;quot;Integralist&amp;quot;&#xA;git config --global user.email &amp;quot;mark@integralist.co.uk&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But this means if I&amp;rsquo;m pushing code for a work project then it&amp;rsquo;ll show those details for the author information. I&amp;rsquo;d rather it show more BBC specific details. So whenever I&amp;rsquo;m working on a BBC project I&amp;rsquo;ll execute:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;switch_github BBCMarkMcDonnell mark.mcdonnell@bbc.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will change the above details to the one&amp;rsquo;s provided. I can then execute it again whenever I switch backed to a personal project, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;switch_github Integralist mark@integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The function is added to my &lt;code&gt;~/.zshrc&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function switch_github() {&#xA;  git config --global user.name $1&#xA;  git config --global user.email $2&#xA;&#xA;  # print updated values just to be sure&#xA;  echo &amp;quot;git config --global user.name: $(git config --global user.name)&amp;quot;&#xA;  echo &amp;quot;git config --global user.email: $(git config --global user.email)&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;alternatives&#34;&gt;Alternatives?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So &lt;a href=&#34;https://twitter.com/sthulb&#34; target=&#34;_blank&#34;&gt;Simon Thulbourn&lt;/a&gt; informed me that he personally would&amp;rsquo;ve used &lt;code&gt;GIT_SSH&lt;/code&gt; as a simpler alternative to the above modification I made to my &lt;code&gt;~/.ssh/config&lt;/code&gt; file. Now the following might not actually be the way he was thinking to do this, but it seems to be the most common route people take using &lt;code&gt;GIT_SSH&lt;/code&gt;, so that&amp;rsquo;s the one I&amp;rsquo;m covering.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way &lt;a href=&#34;https://www.kernel.org/pub/software/scm/git/docs/#_other&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;GIT_SSH&lt;/code&gt;&lt;/a&gt; works is like so:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;When set git fetch and git push will use the specified command&lt;br&gt;&#xA;instead of ssh when they need to connect to a remote system&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So one way we could use this environment variable is like so:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Create the following script file &lt;code&gt;~/.ssh/git.sh&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#!/bin/sh&#xA;&#xA;if [ -z &amp;quot;$PKEY&amp;quot; ]; then&#xA;  ssh &amp;quot;$@&amp;quot; # if PKEY is not specified, run ssh using default keyfile&#xA;else&#xA;  ssh -i &amp;quot;$PKEY&amp;quot; &amp;quot;$@&amp;quot;&#xA;fi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;script originally written by &lt;a href=&#34;https://alvinabad.wordpress.com/2013/03/23/how-to-specify-an-ssh-key-file-with-the-git-command/&#34; target=&#34;_blank&#34;&gt;Alvin Abad&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next we&amp;rsquo;ll need to make this custom script executable:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;chmod +x ~/.ssh/git.sh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;ll need to set &lt;code&gt;GIT_SSH&lt;/code&gt; to point to this script:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;export GIT_SSH=~/.ssh/git.sh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally we can execute our git clone command and specify the key would like it to use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;PKEY=~/.ssh/github_bbc_rsa git clone git@github.com:bbc/mozart.git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Personally I prefer the &lt;code&gt;~/.ssh/config&lt;/code&gt; solution as it feels a little cleaner to me, as apposed to using a custom user script and then still having to specify your key manually every time you git clone. The config route seems simpler.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although that being said, there are quite a few different ways &lt;code&gt;GIT_SSH&lt;/code&gt; can be used (see Alvin Abad&amp;rsquo;s blog post for more ideas). But now you know about &lt;code&gt;GIT_SSH&lt;/code&gt;, maybe you&amp;rsquo;ll find a variation that suits you or you&amp;rsquo;ll decide to just create your own. Enjoy&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;another-alternative&#34;&gt;Another Alternative&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve found all sorts of issues recently with my original solution with things like Ruby&amp;rsquo;s bundler or cli scripts that are hardcoded to use &lt;code&gt;git@github.com&lt;/code&gt; where I can&amp;rsquo;t change it to be a different host.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The solution is a manual step but as I&amp;rsquo;ve managed to automate the process (see below), it&amp;rsquo;s faster than what I was using before and doesn&amp;rsquo;t require me to export any variables or retype the host name AND it actually works across everything (so far).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The downside is that it only works with one other key. If you had to switch between three keys (work, home, other) then you&amp;rsquo;d need to find a different solution (or use the initial solution I defined at the start of this post).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Simply add the following inside your ssh config (I comment it out by default):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# switch&#xA;Host github.com&#xA;  User git&#xA;  HostName github.com&#xA;  IdentityFile ~/.ssh/github_bbc_rsa&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;obviously change the IdentifyFile to point to your own private key&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Then if you have a project that requires you to use your work ssh keys then uncomment it so it becomes active.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve also automated the process using the following alias (the &lt;code&gt;# switch&lt;/code&gt; comment is important, as well as the line number that it starts on in your config file):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;alias sshconfig=&#39;nvim -c &amp;quot;norm 12ggVjjjgc&amp;quot; -c &amp;quot;wq&amp;quot; ~/.ssh/config &amp;amp;&amp;amp; \&#xA;cat ~/.ssh/config | awk &amp;quot;/switch/ {for(i=0; i&amp;lt;=3; i++) {getline; print}}&amp;quot;&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So this uses NeoVim (although it works the same with standard Vim) to open the file and to use Tim Pope&amp;rsquo;s Commentary plugin to toggle the comments around the Host block. My &lt;code&gt;# switch&lt;/code&gt; line starts on line 12 of my config file, so you might need to change the alias to fit your use case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I then use Awk to display only those lines so I can see whether it&amp;rsquo;s toggled on/off.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it. Seems to work fine for me.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/github-multiple-ssh/</guid>
      <link>https://www.integralist.co.uk/posts/github-multiple-ssh/</link>
      <pubDate>Wed, 18 Nov 2015 00:00:00 +0000</pubDate>
      <title>Multiple SSH Keys for Different GitHub Accounts</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a super quick post for demonstrating how to utilise the new HTTP/2 protocol. If you&amp;rsquo;re unfamiliar with it, then let me spend a brief few moments discussing some of the highlights.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;persistent-connections&#34;&gt;Persistent Connections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When using HTTP/1.x each resource your web page specified would need its own connection. If you had three images on a page then that would be three separate connections.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With HTTP/2 the situation is improved by utilising a single connection which supports the concept of a &amp;lsquo;stream&amp;rsquo;. A stream is effectively a two way channel, so information flows up and down it; and a single connection will be able to manage as many streams as necessary.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This removes the need for previous &amp;lsquo;performance&amp;rsquo; techniques such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;domain sharding: a way to side step the problem of browsers only being able to parallelize a limited number of connections to the same domain&lt;/li&gt;&#xA;&lt;li&gt;image spriting: combining multiple images into one to reduce multiple connections to the server&lt;/li&gt;&#xA;&lt;li&gt;concatenating css/js: combining multiples stylesheets or javascript files into a single file to reduce multiple connections to the server&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This also means that the browser is able to more precisely cache resources as there is no need to have to bundle all your static assets together. This also avoids the user downloading assets for a page that they will never visit.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This simply means that multiple resources can be loaded in parallel over a single connection. Just to be clear: this is a very good performance boost and facilitates the ability to transfer lots of resources in a much more efficient manner than HTTP/1.x&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;header-compression&#34;&gt;Header Compression&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Header information will no longer be sent over the wire in plaintext format. It&amp;rsquo;ll now be compressed, making it smaller and the responses subsequently quicker to receive (although admittedly this is only a marginal gain).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This also means we should be less concerned about having to serve static assets from a cookie-less domain, which was a problem because the size of the static resources would all become larger due to cookie data being associated with them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;prioritization&#34;&gt;Prioritization&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Because all connections are multiplexed into a single connection, we need a way to prioritize certain requests over others in order to ensure the fastest possible overall response. HTTP/2 supports the concept of &amp;lsquo;weighting&amp;rsquo; each &amp;lsquo;stream&amp;rsquo; (see &amp;ldquo;Persistent Connections&amp;rdquo; above for details of what a stream is).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wont dive into the specifics of how this has been designed, suffice to say, if you want the gory details then I recommend you read the specification document here: &lt;a href=&#34;http://http2.github.io/http2-spec/#rfc.section.5.3.2&#34; target=&#34;_blank&#34;&gt;http2.github.io/http2-spec&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;ssl-tls&#34;&gt;SSL/TLS&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The above highlights also suggest a reduction in the overall time cost associated with the SSL/TLS &amp;lsquo;handshake&amp;rsquo; process. Here&amp;rsquo;s why:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A single connection will minimize SSL handshaking back and forth between the client/server&lt;/li&gt;&#xA;&lt;li&gt;Multiplexing allows requests to be handled asynchronously&lt;/li&gt;&#xA;&lt;li&gt;Compressing the HTTP headers will make the connection smaller (and subsequently faster)&lt;/li&gt;&#xA;&lt;li&gt;Prioritized connections means allowing relevant requests to be handled in an appropriate order&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;server-push&#34;&gt;Server Push&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In HTTP/2 the server now has the ability to send additional information along with the initial HTTP request made by the client. Now it&amp;rsquo;s important to realise that the concept of &amp;lsquo;server push&amp;rsquo; isn&amp;rsquo;t the same thing as &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events&#34; target=&#34;_blank&#34;&gt;Server-Sent Events&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Server-Sent Events allows the server to push updates to the client and as long as the client is listening for the relevant event, the client will be able to receive the pushed notification.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Server Push isn&amp;rsquo;t the same thing and was designed to solve a different use case. With HTTP/2 the server is able to send the client additional resources, even though the client hadn&amp;rsquo;t explicitly requested them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A typical example given is when the client requests a HTTP page and that page has some static resources like CSS and JavaScript. In HTTP/1.x the client would request a web page, and then start parsing it only to discover the page includes CSS and JavaScript resources. The client would then have to make additional requests for those static resources.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But with HTTP/2 the server can save the client from making multiple requests by sending all the other static resources in parallel for the client&amp;rsquo;s initial request for the main page/document.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;implementations&#34;&gt;Implementations&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Im not sure exactly how many implementations are available for the HTTP/2 specification out in the wild, but there are two that we&amp;rsquo;ll look at here in this article: &lt;a href=&#34;https://www.nginx.com/&#34; target=&#34;_blank&#34;&gt;nginx&lt;/a&gt; and &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in other implementations then you can find a list of alternative options here: &lt;a href=&#34;https://github.com/http2/http2-spec/wiki/Implementations&#34; target=&#34;_blank&#34;&gt;github.com/http2/http2-spec/wiki/Implementations&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;nginx&#34;&gt;Nginx&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The latest release of nginx (both its open-source and paid for models) has good support for HTTP/2, but (for the moment at least) it doesn&amp;rsquo;t support Server Push. I&amp;rsquo;m going to presume that you&amp;rsquo;re already familiar with nginx and how it works, so I won&amp;rsquo;t bother explaining things a basic nginx user would already know.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is a snippet from a &lt;code&gt;nginx.conf&lt;/code&gt; file that has enabled HTTP/2 support:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;http {&#xA;  server {&#xA;    listen *:443 ssl http2;&#xA;    server_name integralist.co.uk;&#xA;&#xA;    ssl_certificate         /etc/nginx/certs/server.crt;&#xA;    ssl_certificate_key     /etc/nginx/certs/server.key;&#xA;    ssl_trusted_certificate /etc/nginx/certs/ca.crt;&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, the &lt;code&gt;listen&lt;/code&gt; directive specifies &lt;code&gt;http2&lt;/code&gt;. In essence this is all you would need to enable HTTP/2 using nginx. The reason we&amp;rsquo;re restricting nginx to listening on port &lt;code&gt;443&lt;/code&gt; and enabling &lt;code&gt;ssl&lt;/code&gt; (+ specifying SSL certificates) is because the majority of web browsers require TLS in order to support HTTP/2, and also nginx&amp;rsquo;s implementation relies upon TLS (see below for details).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;currently Opera and Safari 9 supports HTTP/2 without TLS&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Nginx is a reverse proxy and so because the client doesn&amp;rsquo;t have direct access to the back-end services/applications, nginx is able to translate HTTP/2 into HTTP/1.x which also allows those services to not have to be rearchitected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a client communicates with nginx it&amp;rsquo;ll typically pass a list of protocols it supports along with the request. Nginx will attempt to identify the &lt;code&gt;h2&lt;/code&gt; protocol within that list, which indicates HTTP/2 support (specifically nginx implements the &lt;a href=&#34;https://tools.ietf.org/html/rfc7301&#34; target=&#34;_blank&#34;&gt;Application Layer Protocol Negotiation&lt;/a&gt; extension for TLS). If HTTP/2 isn&amp;rsquo;t supported then nginx falls back to HTTP/1.x instead.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;go&#34;&gt;Go&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re not using a load balancer or a reverse proxy (such as nginx), then you might still be able to implement HTTP/2 support via your application server. One such example is with the Go programming language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example application which demonstrates how to enable HTTP/2 support. Because we&amp;rsquo;re not utilising a reverse proxy we don&amp;rsquo;t have SSL termination handled automatically for us, and so our application will need to handle the TLS handshake process:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;  &amp;quot;fmt&amp;quot;&#xA;  &amp;quot;html&amp;quot;&#xA;  &amp;quot;log&amp;quot;&#xA;  &amp;quot;net/http&amp;quot;&#xA;&#xA;  &amp;quot;golang.org/x/net/http2&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;  var server http.Server&#xA;&#xA;  http2.VerboseLogs = true&#xA;  server.Addr = &amp;quot;:8080&amp;quot;&#xA;&#xA;  http2.ConfigureServer(&amp;amp;server, nil)&#xA;&#xA;  http.HandleFunc(&amp;quot;/&amp;quot;, func(w http.ResponseWriter, r *http.Request) {&#xA;    fmt.Fprintf(w, &amp;quot;URL: %q\n&amp;quot;, html.EscapeString(r.URL.Path))&#xA;    ShowRequestInfoHandler(w, r)&#xA;  })&#xA;&#xA;  log.Fatal(server.ListenAndServeTLS(&amp;quot;localhost.cert&amp;quot;, &amp;quot;localhost.key&amp;quot;))&#xA;}&#xA;func ShowRequestInfoHandler(w http.ResponseWriter, r *http.Request) {&#xA;  w.Header().Set(&amp;quot;Content-Type&amp;quot;, &amp;quot;text/plain&amp;quot;)&#xA;&#xA;  fmt.Fprintf(w, &amp;quot;Method: %s\n&amp;quot;, r.Method)&#xA;  fmt.Fprintf(w, &amp;quot;Protocol: %s\n&amp;quot;, r.Proto)&#xA;  fmt.Fprintf(w, &amp;quot;Host: %s\n&amp;quot;, r.Host)&#xA;  fmt.Fprintf(w, &amp;quot;RemoteAddr: %s\n&amp;quot;, r.RemoteAddr)&#xA;  fmt.Fprintf(w, &amp;quot;RequestURI: %q\n&amp;quot;, r.RequestURI)&#xA;  fmt.Fprintf(w, &amp;quot;URL: %#v\n&amp;quot;, r.URL)&#xA;  fmt.Fprintf(w, &amp;quot;Body.ContentLength: %d (-1 means unknown)\n&amp;quot;, r.ContentLength)&#xA;  fmt.Fprintf(w, &amp;quot;Close: %v (relevant for HTTP/1 only)\n&amp;quot;, r.Close)&#xA;  fmt.Fprintf(w, &amp;quot;TLS: %#v\n&amp;quot;, r.TLS)&#xA;  fmt.Fprintf(w, &amp;quot;\nHeaders:\n&amp;quot;)&#xA;&#xA;  r.Header.Write(w)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the above code has been slightly modified from an example originally conceived by &lt;a href=&#34;https://plus.google.com/111824860449692850794/posts&#34; target=&#34;_blank&#34;&gt;Kim Ilyong&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you stick the above code into a file called &lt;code&gt;http2.go&lt;/code&gt;, run the program and visit &lt;code&gt;https://localhost:8080/&lt;/code&gt; in your browser (using one that supports HTTP/2 obviously), then you should see the following output (or something similar):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;URL: &amp;quot;/&amp;quot;&#xA;Method: GET&#xA;Protocol: HTTP/2.0&#xA;Host: localhost:8080&#xA;RemoteAddr: [::1]:63555&#xA;RequestURI: &amp;quot;/&amp;quot;&#xA;URL: &amp;amp;url.URL{&#xA;    Scheme:&amp;quot;&amp;quot;, &#xA;    Opaque:&amp;quot;&amp;quot;, &#xA;    User:(*url.Userinfo)(nil), &#xA;    Host:&amp;quot;&amp;quot;, &#xA;    Path:&amp;quot;/&amp;quot;, &#xA;    RawPath:&amp;quot;&amp;quot;, &#xA;    RawQuery:&amp;quot;&amp;quot;, &#xA;    Fragment:&amp;quot;&amp;quot;&#xA;}&#xA;Body.ContentLength: 0 (-1 means unknown)&#xA;Close: false (relevant for HTTP/1 only)&#xA;TLS: &amp;amp;tls.ConnectionState{Version:0x303,&#xA; HandshakeComplete:true,&#xA; DidResume:false,&#xA; CipherSuite:0xc02f,&#xA; NegotiatedProtocol:&amp;quot;h2&amp;quot;,&#xA; NegotiatedProtocolIsMutual:true,&#xA; ServerName:&amp;quot;localhost&amp;quot;,&#xA; PeerCertificates:[]*x509.Certificate(nil),&#xA; VerifiedChains:[][]*x509.Certificate(nil),&#xA; SignedCertificateTimestamps:[][]uint8(nil),&#xA; OCSPResponse:[]uint8(nil),&#xA; TLSUnique:[]uint8{0xf6,&#xA; 0xb,&#xA; 0xf8,&#xA; 0x95,&#xA; 0x6f,&#xA; 0x73,&#xA; 0x4f,&#xA; 0x26,&#xA; 0x8f,&#xA; 0x72,&#xA; 0x26,&#xA; 0xab}}&#xA;&#xA;Headers:&#xA;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&#xA;Accept-Encoding: gzip, deflate, sdch&#xA;Accept-Language: en-US,en;q=0.8&#xA;Cache-Control: max-age=0&#xA;Cookie: _chartbeat2=CAgQSrCqRzJnCmxa4b.1434983427317.1434983759085.1&#xA;Dnt: 1&#xA;Upgrade-Insecure-Requests: 1&#xA;User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1)...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice the &lt;code&gt;Protocol: HTTP/2.0&lt;/code&gt; which indicates we&amp;rsquo;re handling HTTP/2 now. If you&amp;rsquo;re using the Chrome web browser you can also download an extension called &amp;ldquo;HTTP/2 and SPDY indicator&amp;rdquo; which will display a blue lightning bolt on any site that is serving content via the HTTP/2 protocol.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://http2.github.io/faq/&#34; target=&#34;_blank&#34;&gt;HTTP/2 FAQ&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/http2/http2-spec/wiki/Implementations&#34; target=&#34;_blank&#34;&gt;HTTP/2 Implementations&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://http2.golang.org/&#34; target=&#34;_blank&#34;&gt;Go HTTP/2 Demo Page&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/bradfitz/http2/tree/master/h2demo&#34; target=&#34;_blank&#34;&gt;Go HTTP/2 Example Code&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/http2/</guid>
      <link>https://www.integralist.co.uk/posts/http2/</link>
      <pubDate>Tue, 20 Oct 2015 00:00:00 +0000</pubDate>
      <title>HTTP/2</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most web developers use a &lt;strong&gt;build tool&lt;/strong&gt; of some sort nowadays. I’m not refering to continuous integration software like &lt;a href=&#34;http://jenkins-ci.org/&#34; target=&#34;_blank&#34;&gt;Jenkins CI&lt;/a&gt; (a very popular build system), but the lower-level software it uses to actually acquire dependencies and construct your applications with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is a dizzying array of options to choose from:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://ant.apache.org/&#34; target=&#34;_blank&#34;&gt;Apache Ant&lt;/a&gt; (XML-based)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.seattlerb.org/rake/&#34; target=&#34;_blank&#34;&gt;Rake&lt;/a&gt; (Ruby-based)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://gruntjs.com/&#34; target=&#34;_blank&#34;&gt;Grunt&lt;/a&gt; (JS-based)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://gulpjs.com/&#34; target=&#34;_blank&#34;&gt;Gulp&lt;/a&gt; (JS-based)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/broccolijs/broccoli&#34; target=&#34;_blank&#34;&gt;Broccoli&lt;/a&gt; (JS-based)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.npmjs.com/&#34; target=&#34;_blank&#34;&gt;NPM&lt;/a&gt; (JS-based)&lt;/li&gt;&#xA;&lt;li&gt;Good ol’ shell scripts (although no real orchestration around it)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The build tool I want to look at in more detail here though is the granddaddy of them all: &lt;a href=&#34;http://www.gnu.org/software/make/&#34; target=&#34;_blank&#34;&gt;Make&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Originally designed back in 1976, Make is the leading build utility for Unix, Linux and Mac OS X. Chances are, most computers you log in to will already have it installed and available to use. This really reduces the set-up entry point (which for other tools listed above can be tedious and error prone – with the exception of shell scripts, as the shell is something inherently available for all systems).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My hope is for you to see that Make is an automation/orchestration tool that can be used in place of other modern build tools, and will help to strengthen your understanding and ability to use the terminal/shell environment (which is a big plus in my opinion, and helps open up many avenues of technical progression).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I couldn’t hope to cover every aspect of what Make offers, so please don’t mistakenly consider this post as anything even remotely exhaustive. Whole books have been written on the topic of Make and writing Makefiles so I’ll leave it up to you to investigate further beyond this post if I’ve managed to kindle your interest.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let me start by referencing the &lt;a href=&#34;http://www.gnu.org/software/make/&#34; target=&#34;_blank&#34;&gt;GNU website&lt;/a&gt; for its definition of what Make is and does:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program’s source files&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Make relies on a &lt;em&gt;Makefile&lt;/em&gt; being defined and which consists of a set of instructions for building your software. If you’ve used another build system, such as &lt;a href=&#34;http://gruntjs.com&#34; target=&#34;_blank&#34;&gt;Grunt&lt;/a&gt;, you’ll notice that most of them use a naming convention taken from Make (e.g. &lt;em&gt;Gruntfile&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The point of a Makefile (in the traditional sense) is to build a program; although Make can be used to run any kind of task and so it isn’t limited to compiling software. Much like how other JavaScript-based build tools aren’t limited to building JavaScript applications, they can handle most tasks you wish to run (maybe compiling CSS or optimizing images).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’ll find Make is widely distributed and is likely already on your computer. For example, I’m using an Apple laptop with Mac OS X installed. If I run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;make --version&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I get back the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;GNU Make 3.81&#xA;Copyright (C) 2006  Free Software Foundation, Inc.&#xA;This is free software; see the source for copying conditions.&#xA;There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A&#xA;PARTICULAR PURPOSE.&#xA;&#xA;This program built for i386-apple-darwin11.3.0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which means I already have the &lt;code&gt;make&lt;/code&gt; command available and I can start writing my Makefile right away.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;simple-example&#34;&gt;Simple Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let’s consider a standard project requirement, which is to run a linter such as &lt;a href=&#34;http://www.jshint.com/&#34; target=&#34;_blank&#34;&gt;JSHint&lt;/a&gt; over a JavaScript file (that is, analyze the code for formatting issues and general errors and warnings).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as mentioned earlier, traditionally Make is used to compile program files. In this instance I’ve opted for a simple example that doesn’t require compilation but should instead demonstrate how Make is actually useful for many different types of task.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a &lt;em&gt;test.js&lt;/em&gt; file and it contains the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function foo() {&#xA;  bar = &amp;quot;baz&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we were to execute the command &lt;code&gt;jshint test.js --show-non-errors&lt;/code&gt; (assuming you have the CLI version of JSHint installed) then we should see something like the following displayed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;test.js: line 2, col 14, Missing semicolon.&#xA;&#xA;1 error&#xA;&#xA;test.js :&#xA;  Implied globals:&#xA;    bar: 2&#xA;  Unused Variables:&#xA;    foo(1),&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So we can see from this output that JSHint is warning us that we have a function &lt;code&gt;foo&lt;/code&gt; that’s not being used and a variable that appears to have been declared globally; but it also indicates that we have an error in our program: we’re missing a semicolon from line 2 in our JavaScript file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK great, so how do we take this example further and automate the analysis process (which will get more complicated as our application grows in size and features) using the Make utility?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First we need to create a &lt;em&gt;Makefile&lt;/em&gt;. Below are the contents of the Makefile I’m going to use to demonstrate how Make works (I’ll explain the structure of the file in the next section):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;lint&#xA;  jshint *.js --show-non-errors&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Makefiles use tabs instead of spaces, so if your editor is set up to replace spaces with tabs then you could find things don’t work as expected&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To run the Makefile above, we would need to use the &lt;code&gt;make&lt;/code&gt; shell command. This by itself will run the first target it finds (this is also referred to as the &lt;em&gt;default target&lt;/em&gt;) which in this case is &lt;code&gt;lint&lt;/code&gt;. You can also be more explicit and specify the exact target you want to execute by providing the name of the target to the &lt;code&gt;make&lt;/code&gt; command, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;make lint&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Executing the above command is the same as running:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;jshint test.js --show-non-errors&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You’ll also have noticed we used a wildcard &lt;code&gt;*&lt;/code&gt; to indicate multiple JavaScript files at once.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this instance, using Make means it’s easier to remember specific commands for common tasks such as this. Having to remember the format of the JSHint shell command is now not an issue, especially considering that I’m using the most bare bones example of running JSHint, and the shell command itself can become much longer and unwieldy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Makefile also acts as a documented file that can now be committed into version control, meaning we now have a record of the compilation step. Both these points become even more important as the compilation/build steps become more and more complicated, which they will as your application or software system naturally grows and evolves.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if your Makefile is in a different directory, you can pass its location to the &lt;code&gt;make&lt;/code&gt; command using the &lt;code&gt;-f&lt;/code&gt; flag like so: &lt;code&gt;make -f &amp;lt;makefile&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The convention for writing Makefiles is to have the default command (your entry point) at the top of the file and have Make process the commands from the top down. You don’t have to do this, though (as you’ll see, I’ve not really worried about it with the examples throughout this post), and you’re free to put your rules in whatever order makes sense to you. But be aware that when you call the Make command, you’ll want to specify the specific target if it’s not the default.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are three key phrases you need to be aware of when talking about a Makefile:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Rules&lt;/li&gt;&#xA;&lt;li&gt;Targets&lt;/li&gt;&#xA;&lt;li&gt;Prerequisites&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The following snippet demonstrates the basic structure of a Makefile:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;target: prereq1 prereq2&#xA;    commands&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see we have: a single target (this is what we reference when running the command &lt;code&gt;make &amp;lt;target&amp;gt;&lt;/code&gt;); a set of dependencies (i.e. prerequisites); and a command to execute (e.g. &lt;code&gt;jshint test.js --show-non-errors&lt;/code&gt;). This entire structure is collectively referred to as a “rule” and a Makefile is typically made up of multiple rules.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Prerequisites are the dependencies for the target. What this means is that the target cannot be built successfully without the dependencies first being resolved.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine we’re compiling Sass into CSS. An example Makefile (which we’ll look at in more detail shortly) could look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;compile: foo.scss&#xA;    sass foo.scss foo.css&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example we specified the prerequisite as being &lt;code&gt;foo.scss&lt;/code&gt;; meaning Make will either look for a target called &lt;code&gt;foo.scss&lt;/code&gt; or expect a file to exist in the current directory structure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We don’t have a target named &lt;code&gt;foo.scss&lt;/code&gt; and so if that file also didn’t exist, then we couldn’t resolve the dependency and subsequently the rule would fail (if it can’t resolve the dependency then the command in the rule won’t be executed).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-make-decides-what-to-do&#34;&gt;How Make Decides What To Do&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;How and why Make decides what to do when you run &lt;code&gt;make &amp;lt;target&amp;gt;&lt;/code&gt; is very important as it’ll help you understand the performance implications of certain tasks. The rule of thumb for Make is pretty simple: if the target (or any of its prerequisite files) are out of date or missing, then the commands for that target will be executed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Make uses the modification timestamp to avoid duplicate processing. If the timestamp of the dependent files is older than the resulting output, then running Make won’t do anything. Hence you can force Make to recompile a file by simply using the &lt;code&gt;touch&lt;/code&gt; command on the relevant files.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you want to see what Make will execute without it actually doing anything, then run the &lt;code&gt;make&lt;/code&gt; command as you normally would but ensure you include the &lt;code&gt;-n&lt;/code&gt; flag. This will cause Make to print out all commands that would be executed, including commands collated from any specified prerequisites.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;automatic-variables&#34;&gt;Automatic variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let’s consider another example whereby we want to compile a &lt;a href=&#34;http://sass-lang.com/&#34; target=&#34;_blank&#34;&gt;Sass&lt;/a&gt; style sheet into CSS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;compile: foo.scss&#xA;    sass foo.scss foo.css&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We have some slight duplication here, the reference to &lt;em&gt;foo.scss&lt;/em&gt;. We can clean this up a bit by using some special variables that Make provides (also referred to as automatic variables). Specifically for the problem we want to solve, we’ll be using the &lt;code&gt;$&amp;lt;&lt;/code&gt; automatic variable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When the &lt;code&gt;compile&lt;/code&gt; target is run, the &lt;code&gt;$&amp;lt;&lt;/code&gt; variable will reference the first prerequisite in the list, which will simplify the example and save you from having to repeat yourself. The following example demonstrates what this looks like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;compile: foo.scss&#xA;    sass $&amp;lt; foo.css&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is good because we’ve removed a hardcoded value and made our code slightly more flexible. But what happens if we have multiple dependencies?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Assume we have three files &lt;em&gt;foo.txt&lt;/em&gt;, &lt;em&gt;bar.txt&lt;/em&gt; and &lt;em&gt;baz.txt&lt;/em&gt;. We can use a combination of the &lt;code&gt;$^&lt;/code&gt; variable (which gives us all the dependencies/prerequisites as a list) and a small bit of standard &lt;a href=&#34;http://en.wikipedia.org/wiki/Bash_%28Unix_shell%29&#34; target=&#34;_blank&#34;&gt;Bash shell&lt;/a&gt; code (Make commands are ultimately structured shell scripts with extra syntactical sugar) to loop over the provided dependency list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how this could be written:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;list: foo.txt bar.txt baz.txt&#xA;    for i in $^; do echo &amp;quot;Dependency: $$i&amp;quot;; done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Executing &lt;code&gt;make list&lt;/code&gt; would result in the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;for i in foo.txt bar.txt baz.txt; do echo &amp;quot;Dependency: $i&amp;quot;; done&#xA;Dependency: foo.txt&#xA;Dependency: bar.txt&#xA;Dependency: baz.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because Makefiles have their own special syntax, the use of &lt;code&gt;$&lt;/code&gt; will conflict when writing our shell script (which also has its own special syntax around &lt;code&gt;$&lt;/code&gt;). This means if we want to use the dollar character and not have it be Makefile specific, then we have to escape it using another dollar. So rather than writing &lt;code&gt;$i&lt;/code&gt; – which works fine within the context of a normal shell script – we’ve had to write &lt;code&gt;$$i&lt;/code&gt; instead.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We’ll see a few different automatic variables throughout this post, but in the meantime check out the quick reference list below for some of the more useful ones:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;$&amp;lt;&lt;/code&gt;: first prerequisite&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$^&lt;/code&gt;: list of prerequisites&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$?&lt;/code&gt;: list of prerequisites that have changed&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$@&lt;/code&gt;: target name&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$*&lt;/code&gt;: the value of a target placeholder&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables&#34; target=&#34;_blank&#34;&gt;full reference of automatic variables&lt;/a&gt; is available on the GNU Make website.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Later on in this post we’ll revisit this &lt;code&gt;for&lt;/code&gt; loop example and demonstrate a more idiomatic way to achieve the result we want.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;commands&#34;&gt;Commands&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It’s worth being aware that each command provided inside the overall rule is considered a separate shell context. This means if you export a shell environment variable in one command, it won’t be available within the next command. Once the first command has finished, a fresh shell is spawned for the next command, and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’ll also notice that when running Make it will print out the command instructions &lt;em&gt;before&lt;/em&gt; executing them. This can be disabled in one of three ways. You can either run Make with the &lt;code&gt;-s&lt;/code&gt; flag, which will silence any output; or you can use the &lt;code&gt;@&lt;/code&gt; syntax before the command itself, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;list: foo.txt bar.txt baz.txt&#xA;    @for i in $^; do echo &amp;quot;Dependency: $$i&amp;quot;; done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The third way to silence output is to use the &lt;code&gt;.SILENCE&lt;/code&gt; flag. The following snippet demonstrates how to silence three targets: &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.SILENT: foo bar baz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;silencing the output unfortunately also means silencing any errors!&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Much like shell scripting, if you have a command that is more complicated than what can feasibly fit on a single line, then – for the sake of readability if nothing else – you’ll need to write it across multiple lines and escape the line breaks using the &lt;code&gt;\&lt;/code&gt; character, as the following example demonstrates:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;list: foo.txt bar.txt baz.txt&#xA;    for i in $^; do \&#xA;        echo &amp;quot;Dependency: $$i&amp;quot;; \&#xA;    done&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;targets-as-prerequisites&#34;&gt;Targets As Prerequisites&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So far our prerequisites have been physical files that already existed. But what if you need to dynamically create the files first via other targets? Make allows you to specify targets as dependencies, so that’s not a problem. Let’s see how this works in the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo:&#xA;    @echo foo &amp;gt; foo-file.txt&#xA;&#xA;bar:&#xA;    @echo bar &amp;gt; bar-file.txt&#xA;&#xA;baz: foo bar&#xA;    @echo baz | cat - foo-file.txt bar-file.txt &amp;gt; baz-file.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Make typically uses the convention of naming targets after the files they create. This isn’t a necessity but it’s generally considered good practice&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What we have are three targets: &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt;. The first two have no dependencies of their own and all they do is generate a new text file. The last target, &lt;code&gt;baz&lt;/code&gt;, specifies the other two targets as its dependencies. So when we run &lt;code&gt;make baz&lt;/code&gt; we should see no output (as we’ve used the special &lt;code&gt;@&lt;/code&gt; syntax to silence any output) but we should find we have the following files created:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;foo-file.txt&lt;/em&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;bar-file.txt&lt;/em&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;baz-file.txt&lt;/em&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The last file in the list should contain not only a line that displays &lt;code&gt;baz&lt;/code&gt; but also two other lines comprising the contents of the other files. So running &lt;code&gt;cat baz-file.txt&lt;/code&gt; should print:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;baz&#xA;foo&#xA;bar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you’ve not seen it used before, the &lt;code&gt;-&lt;/code&gt; in the &lt;code&gt;cat&lt;/code&gt; command is telling it to expect input from stdin (the &lt;code&gt;echo&lt;/code&gt; command writes to stdout and that is piped &lt;code&gt;|&lt;/code&gt; over to the &lt;code&gt;cat&lt;/code&gt; command as stdin)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;accessing-targets&#34;&gt;Accessing Targets&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In the above example, I was generating a file based on the contents of two other targets (which themselves dynamically generated some files). There was a slight bit of repetition that could have been cleaned up if we used another automatic variable provided by Make, specifically &lt;code&gt;$@&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;$@&lt;/code&gt; variable is a reference to the target name, so let’s see how we can use this with our previous example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo:&#xA;    @echo $@ &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&#xA;bar:&#xA;    @echo $@ &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&#xA;baz: foo bar&#xA;    @echo $@ | cat - foo-file.txt bar-file.txt &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the example above we’ve saved ourselves from typing &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;baz&lt;/code&gt; a few times but we’ve not eradicated them completely as we still have to reference &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; as prerequisites, as well as referencing them from within the &lt;code&gt;baz&lt;/code&gt; command itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With regards to the &lt;code&gt;baz&lt;/code&gt; command, we could use &lt;code&gt;$^&lt;/code&gt; along with some shell scripting to clean that up so we’re again not relying on hardcoded values. The following example shows how to achieve that:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo:&#xA;    @echo $@ &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&#xA;bar:&#xA;    @echo $@ &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&#xA;baz: foo bar&#xA;    @files=$$(echo $^ | sed -E &#39;s/([a-z]+)/\1-file.txt/g&#39;); echo $@ | cat - $$files &amp;gt; &amp;quot;$@-file.txt&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Oh boy, OK. So yes, we’ve removed some more hardcoded values, but unless you’re supremely confident with shell scripting then I’m guessing the above refactor won’t make much sense to you. But let’s break it down a bit so we can see what we have:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We use &lt;code&gt;$^&lt;/code&gt; to get the list of dependencies; in this case, &lt;code&gt;foo bar&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;We pipe that over to the &lt;code&gt;sed&lt;/code&gt; command. We also use the extended regular expression engine &lt;code&gt;-E&lt;/code&gt; to make our regex pattern easier to understand.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;sed&lt;/code&gt; command replaces &lt;code&gt;foo bar&lt;/code&gt; with &lt;code&gt;foo-file.txt bar-file.txt&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;We do that replacement within a subprocess &lt;code&gt;$()&lt;/code&gt;, which is a special shell syntax. This means we have to escape the dollar sign within the Makefile (&lt;code&gt;$$()&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;The values returned from the subprocess (&lt;code&gt;foo-file.txt bar-file.txt&lt;/code&gt;) are then stored in a variable called &lt;code&gt;files&lt;/code&gt; and we reference that variable in place of the original hardcoded values.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;On top of all that, we &lt;em&gt;still&lt;/em&gt; have duplication: the &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; referenced within the prerequisites area. That has to be hardcoded unless we’re going to use Make or some other form of shell scripting to dynamically generate the actual Makefile itself; which even for me is a step too far in this case.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, so what does this ultimately tell us? That simplicity is the key.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I went to all this trouble is it allowed me to demonstrate first, how to really stretch what Make can do for you if you have enough shell scripting knowledge; and second, to allow me to now demonstrate how you can use more idiomatic Make to simplify the code and avoid overengineering like the previous example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;baz: foo-file.txt bar-file.txt&#xA;  echo $@ | cat - $^ &amp;gt; $@-file.txt&#xA;&#xA;%-file.txt:&#xA;  echo $* &amp;gt; $@&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this refactored version we define a target called &lt;code&gt;baz&lt;/code&gt; and we set its dependencies to be two files that don’t exist. We also don’t have any defined targets in our Makefile either.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To solve this problem we use a virtual rule, one that uses Make’s &lt;code&gt;%&lt;/code&gt; placeholder syntax to pattern match against. We’ll see the &lt;code&gt;%&lt;/code&gt; syntax in more detail shortly, but for now it will suffice to know that it acts like a wildcard.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we run &lt;code&gt;make baz&lt;/code&gt;, Make will try to resolve the two dependencies. The following rule &lt;code&gt;%-file.txt&lt;/code&gt; will then match both &lt;code&gt;foo-file.txt&lt;/code&gt; and &lt;code&gt;bar-file.txt&lt;/code&gt; and so the command &lt;code&gt;echo $* &amp;gt; $@&lt;/code&gt; will be executed twice.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The command takes the dynamic part of the rule (the &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt; parts) and makes them available via &lt;code&gt;$*&lt;/code&gt;. We write those two values into &lt;code&gt;$@&lt;/code&gt;, which is the target name (in this case &lt;code&gt;foo-file.txt&lt;/code&gt; and &lt;code&gt;bar-file.txt&lt;/code&gt;) and subsequently create those two files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We’ve now resolved the &lt;code&gt;baz&lt;/code&gt; rule’s dependencies and we can move on to executing its command, which completes the requirements as we’ve already seen.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;parsing-targets-and-prerequisites&#34;&gt;Parsing Targets And Prerequisites&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many different automatic variables available for Make and we’ll see a few more of them as we go along. But as we’ve already discussed &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$&amp;lt;&lt;/code&gt;, it’s worth noting that you are also able to parse the specific directory and file name details for the first dependency and the target by using the syntax &lt;code&gt;$(&amp;lt;D)&lt;/code&gt;/&lt;code&gt;$(&amp;lt;F)&lt;/code&gt; for the prerequisite, and &lt;code&gt;$(@D)&lt;/code&gt;/&lt;code&gt;$(@F)&lt;/code&gt; for the target.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the following snippet as an example (you would run it with &lt;code&gt;make foo/bar/baz.txt&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bing/bop.txt:&#xA;    @# do nothing&#xA;&#xA;foo/bar/baz.txt: bing/bop.txt&#xA;    @echo $(@D)&#xA;    @echo $(@F)&#xA;    @echo -------&#xA;    @echo $(&amp;lt;D)&#xA;    @echo $(&amp;lt;F)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The example above would output first the directory structure and then the file name which has been parsed from the target, and after that the directory structure and file name parsed from the prerequisite:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo/bar&#xA;baz.txt&#xA;-------&#xA;bing&#xA;bop.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Depending on your requirements this can be quite a powerful tool to help you construct more complex commands.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you’re interested in knowing where your &lt;code&gt;make&lt;/code&gt; binary is located then you can use the built-in &lt;code&gt;MAKE&lt;/code&gt; special variable in your command: &lt;code&gt;@echo $(MAKE)&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;dynamic-targets&#34;&gt;Dynamic Targets&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Targets can dynamically match mulitiple unknown values and allow for abstracting away common functionality, such as generating files that have similar names (to give a simplified example).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this we need to take advantage of the placeholder syntax &lt;code&gt;%&lt;/code&gt;, and its corresponding &lt;code&gt;$*&lt;/code&gt; syntax. The following example demonstrates the basic structure:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dynamic-%:&#xA;    @echo &amp;quot;Placeholder value: $* and target value: $@&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you run the target using &lt;code&gt;make dynamic-foo&lt;/code&gt; then you’ll get the following response (notice that the dynamic aspect of the command &lt;code&gt;foo&lt;/code&gt; is captured in the placeholder):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Placeholder value: foo and target value: dynamic-foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;dereferencing-variables-and-macros&#34;&gt;Dereferencing (Variables and Macros)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Make provides the multipurpose utility &lt;code&gt;$()&lt;/code&gt;, which is used to dereference values. The values can be functions (Make has many functions built in and we’ll take a quick glance at some of them later on) or they can be variable names. Let’s consider a simple example where we dereference a variable:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;some_var := abc&#xA;&#xA;print_var:&#xA;    @echo $(some_var)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the above example that we defined the variable using the &lt;code&gt;:=&lt;/code&gt; syntax (whereas with most languages you would assign a value to a variable using &lt;code&gt;=&lt;/code&gt;). Make also supports &lt;code&gt;=&lt;/code&gt; as an alternative assignment operator but its use is specifically for situations where you need to take advantage of recursive dereferencing. Let’s see what that means in practice by reviewing the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo = $(bar)&#xA;bar = $(baz)&#xA;baz = qux value here&#xA;&#xA;recursive:&#xA;    @echo $(foo)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This returns &lt;code&gt;qux value here&lt;/code&gt; and demonstrates how the &lt;code&gt;foo&lt;/code&gt; variable recursively evaluated all other values thanks to the &lt;code&gt;=&lt;/code&gt; operator.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we tried this using &lt;code&gt;foo := $(bar)&lt;/code&gt; instead, then the &lt;code&gt;recursive&lt;/code&gt; target would have printed out an empty line as it uses a straightforward simple expansion algorithm, which means its right-hand side value is expanded immediately (i.e. expanded at declaration time). With this example, Make doesn’t recursively expand the values back to &lt;code&gt;bar&lt;/code&gt; and subsequently back to &lt;code&gt;baz&lt;/code&gt; to find the final value of &lt;code&gt;qux value here&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are also other types of assigment you can use, such as conditional variable &lt;code&gt;?=&lt;/code&gt;. What that will do is assign a value to the defined variable only if it doesn’t already have a value defined. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;assignment = foo&#xA;assignment ?= bar&#xA;&#xA;conditional_assignment:&#xA;    @echo $(assignment)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we run &lt;code&gt;make conditional_assignment&lt;/code&gt;, then we’ll see the value &lt;code&gt;foo&lt;/code&gt; printed. The value &lt;code&gt;bar&lt;/code&gt; isn’t assigned as a value was already defined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One other assignment type worth considering is &lt;code&gt;+=&lt;/code&gt;, which works pretty much as you would expect it to if you’re a programmer (as it’s an operator that appears in many different languages). Effectively it appends the value onto the variable, keeping the original value as well. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;hello_world = hello&#xA;hello_world += world&#xA;&#xA;say_hello:&#xA;    @echo $(hello_world)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The example above prints &lt;code&gt;hello world&lt;/code&gt;, as it has appended &lt;code&gt;world&lt;/code&gt; onto the existing value &lt;code&gt;hello&lt;/code&gt;. Interestingly, Make automatically puts in a space as well between the values assigned (notice the value printed wasn’t &lt;code&gt;helloworld&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One last thing I want to cover is the use of macros in Make. A macro is a collection of commands that are expanded and executed when dereferenced. It’s a lot like a function, in that it groups behavior. The following example demonstrates how it works:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;define do_lots_of_things&#xA;  echo Hi there&#xA;  echo I do lots of things&#xA;  echo So it\&#39;s best I do this in this macro&#xA;endef&#xA;&#xA;stuff:&#xA;    @$(do_lots_of_things)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When we execute &lt;code&gt;make stuff&lt;/code&gt; we see all the different messages printed to the screen. We could reuse this macro in many different target rules if we wanted to as well, which is really the whole point of them.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;notice that I had to escape the use of the single quote &lt;code&gt;&#39;&lt;/code&gt;. This was done because without it the command would fail due to a syntax error in Make.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As mentioned in the previous section, the &lt;code&gt;$()&lt;/code&gt; utility worked to dereference a value, but it can also handle a number of built-in functions. Although some of the functions could be replaced with standard shell commands.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;a &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Functions.html&#34; target=&#34;_blank&#34;&gt;full list of functions&lt;/a&gt; can be found on the GNU Make website.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;filter&#34;&gt;Filter&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Let’s take a look at some interesting functions Make provides. The first one I like the look of is &lt;code&gt;filter&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;filter: foo.txt bar.txt baz.txt&#xA;    @echo $(filter ba%.txt, $^)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this rule we use the &lt;code&gt;filter&lt;/code&gt; function, which takes as its first argument the pattern you want to try to match and the text you want to search within. In our example the text to be searched is the list of prerequisites (using &lt;code&gt;$^&lt;/code&gt; which we’ve already seen). The pattern we’re hoping to match uses the &lt;code&gt;%&lt;/code&gt; placeholder wildcard value and the filter returns only files that begin with &lt;code&gt;ba&lt;/code&gt; and end in &lt;code&gt;.txt&lt;/code&gt;. This results in &lt;code&gt;bar.txt baz.txt&lt;/code&gt; that is printed.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;shell&#34;&gt;Shell&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Outside of a target you can have a variable dynamically pull data from the shell environment by using the &lt;code&gt;v := $(shell &amp;lt;command&amp;gt;)&lt;/code&gt; pattern.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because we’re using the &lt;code&gt;shell&lt;/code&gt; function, we use &lt;code&gt;:=&lt;/code&gt; for simple expansion rather than &lt;code&gt;=&lt;/code&gt;, which would allow for recursive dereferencing and could cause problems depending on what your Makefile and shell script is doing.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the following example we use the &lt;code&gt;shell&lt;/code&gt; function to calculate the result of adding 1 and 1. We then dereference that value from within our target:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;calculation := $(shell echo $$((1 + 1)))&#xA;shelled_value:&#xA;    @echo $(calculation)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the shell, to do arithmetic (and other such things) we need to use the expression utility &lt;code&gt;$((...))&lt;/code&gt;, so don’t make the mistake of thinking it’s a syntax special to Make, because it’s not.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;eval&#34;&gt;Eval&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the following snippet we use the &lt;code&gt;eval&lt;/code&gt; function to create a Makefile variable dynamically at runtime:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dyn_eval:&#xA;    $(eval FOOBAR:=$(shell echo 123))&#xA;    @echo $(FOOBAR)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We use the &lt;code&gt;shell&lt;/code&gt; function to return a dynamically generated value (in this case &lt;code&gt;123&lt;/code&gt;) and we assign that to a variable FOOBAR. But to allow us to access FOOBAR from other commands within this target, as well as other unrelated targets, we use &lt;code&gt;eval&lt;/code&gt; to create the variable globally. Finally, we use &lt;code&gt;$()&lt;/code&gt; to dereference the variable.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;files&#34;&gt;Files&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following technique allows us to carry out simple substitutions, by swapping the matched text before the &lt;code&gt;=&lt;/code&gt; with the text that follows it. The defined pattern is then applied to the variable being dereferenced:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;files = foo.txt bar.txt baz.txt&#xA;change_ext:&#xA;    @echo $(files:.txt=.doc)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above example produces the following output (notice how the &lt;code&gt;files&lt;/code&gt; list of files now have &lt;code&gt;.doc&lt;/code&gt; extensions):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foo.doc bar.doc baz.doc&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;There are many functions and techniques to help you extend the capabilities within Make and so I would highly recommend you have a read through &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Functions.html&#34; target=&#34;_blank&#34;&gt;the functions listed in the GNU Make manual&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;user-defined-functions&#34;&gt;User-Defined Functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You’ve already seen the use of macros via the syntax &lt;code&gt;define&lt;/code&gt;. User-defined functions work exactly the same way but you call them differently to macros (you’ll use the Make built-in &lt;code&gt;call&lt;/code&gt; function), and this is so that you can pass arguments to the definition. This is best demonstrated with an example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;define foo&#xA;  @echo &amp;quot;I was called with the argument:$1&amp;quot;&#xA;endef&#xA;&#xA;call_foo:&#xA;    $(call foo, &amp;quot;hello!&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The example above would be executed with &lt;code&gt;make call_foo&lt;/code&gt;, and would result in the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;I was called with the argument: hello!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;earlier we noticed that Make would include a space when using the &lt;code&gt;+=&lt;/code&gt; operator. The same happens with function arguments and so when creating the string that is printed I didn’t include a space after the &lt;code&gt;:&lt;/code&gt; but the output shows a space thanks to Make.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You can pass as many arguments as you like to a function and it’ll be accessible numerically (e.g. &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, &lt;code&gt;$3&lt;/code&gt; and so on). You can also call other functions from within a function and pass on the arguments, or pass different arguments using the &lt;code&gt;$(call function_name)&lt;/code&gt; syntax.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conventions&#34;&gt;Conventions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are some well-known conventions and idioms used by the Make community, and a few of the most prominent ones are detailed in this section.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first is the inclusion of a &lt;code&gt;clean&lt;/code&gt; target which should be used to remove any files created by your Makefile. This is to allow you to clean up after your tasks have executed (or if things have gone haywire). Typically the default target will specify &lt;code&gt;clean&lt;/code&gt; as a prerequisite so as to clear your workspace before starting a fresh build.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second is to have a &lt;code&gt;help&lt;/code&gt; target which &lt;code&gt;echo&lt;/code&gt;s each of the targets within the file and explains its purpose. As demonstrated below:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;help:&#xA;    @echo foo: does foo stuff&#xA;    @echo bar: does bar stuff&#xA;    @echo baz: does baz stuff&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you could use some clever shell scripting along with Makefile comments to dynamically generate the printed commands and their descriptions (e.g. read in the Makefile source and parse out the meta data/comments as part of a sub shell &lt;code&gt;$(shell ...)&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The third is to include a reference to a special target called &lt;code&gt;.PHONY&lt;/code&gt; at either the top or bottom of your Makefile, followed by a list of target names. The purpose of &lt;code&gt;.PHONY&lt;/code&gt; is to prevent conflicts with files within your current project directory that coincidentally match the name of your Makefile targets.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To clarify what this means in practical terms: Make has a convention whereby you would define a target’s name as matching the name of the file the commands will ultimately create; because although Make is useful for general purpose tasks, it was originally designed for creating application files. Make will associate a target with any file that matches its name and will intelligently monitor the dependencies for the target to see if it’s OK to re-execute the target’s command to regenerate the file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically a target such as &lt;code&gt;clean&lt;/code&gt; won’t have any dependencies (not all the time mind you, but most of the time it won’t because the purpose of &lt;code&gt;clean&lt;/code&gt; is to remove generated files; it shouldn’t depend on any other files in order to complete that action). If a target has no dependencies then Make will always run the associated commands. Remember, Make can intelligently avoid running certain commands if it knows the dependencies haven’t changed at all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By specifying &lt;code&gt;clean&lt;/code&gt; as being a “phony” target, it means if there was ever a file called &lt;code&gt;clean&lt;/code&gt; added to your project then we could avoid confusion as to how Make should handle running the target. The following demonstrates how it is used. It assumes you have a file – with no file extension – called &lt;code&gt;clean&lt;/code&gt; in your main project directory:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.PHONY: clean&#xA;&#xA;clean:&#xA;    @echo &amp;quot;I&#39;ll do something like remove all files&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example, running &lt;code&gt;make clean&lt;/code&gt; will display the message “I’ll do something like remove all files”. But if you remove the &lt;code&gt;.PHONY: clean&lt;/code&gt; and rerun the target (using &lt;code&gt;make clean&lt;/code&gt;) you’ll now find, because we have a &lt;code&gt;clean&lt;/code&gt; file in our main project directory and no dependencies for that target, that Make will mistakenly think there is nothing left to do and so it displays the message:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;make: &#39;clean&#39; is up to date.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;like with automatic variables, there are many different special targets (so far we’ve seen &lt;code&gt;.PHONY&lt;/code&gt; and &lt;code&gt;.SILENT&lt;/code&gt;). One that’s worth further investigation is &lt;code&gt;.DELETE_ON_ERROR&lt;/code&gt;, which indicates to Make that if any of the commands for your target rule fails then it should delete the associated target file in your project. A &lt;a href=&#34;https://www.gnu.org/software/make/manual/html_node/Special-Targets.html&#34; target=&#34;_blank&#34;&gt;list of special targets&lt;/a&gt; is available on the GNU Make website.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;revisiting-the-for-loop-example&#34;&gt;Revisiting The For Loop Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Earlier on we looked at a way of using a for loop as a command to loop over a list of text files and to print their names.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let’s now consider two alternative ways of achieving this. The first uses a few more Make functions, while the second is more readable – but ultimately they use similar solutions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is the first alternative:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;my_list = $(addsuffix .dep, $(wildcard *.txt))&#xA;print_list: $(my_list)&#xA;%.dep: %&#xA;  @echo &amp;quot;Text File:&amp;quot; $&amp;lt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The first thing we do is use the &lt;code&gt;wildcard&lt;/code&gt; function to retrieve a list of text files (this is equivalent to &lt;code&gt;$(shell ls *.txt)&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;We then use the &lt;code&gt;addsuffix&lt;/code&gt; function to convert something like &lt;code&gt;foo.txt&lt;/code&gt; into &lt;code&gt;foo.txt.dep&lt;/code&gt;. This doesn’t actually create any files, by the way; you’ll see why we do this in a moment.&lt;/li&gt;&#xA;&lt;li&gt;Next we create a target called &lt;code&gt;print_list&lt;/code&gt; and we set its dependencies to be the &lt;code&gt;my_list&lt;/code&gt; list of file names (e.g. &lt;code&gt;foo.txt.dep bar.txt.dep baz.txt.dep&lt;/code&gt;). But obviously there are no such targets defined in our Makefile so this leads us to the next step.&lt;/li&gt;&#xA;&lt;li&gt;We dynamically create targets that would match what’s found in &lt;code&gt;my_list&lt;/code&gt; using a placeholder, and we set the dependency for these dynamic targets to be the text file itself. Remember that the target &lt;code&gt;%.dep&lt;/code&gt; would match &lt;code&gt;foo.txt.dep&lt;/code&gt; and so subsequently setting the dependency to just &lt;code&gt;%&lt;/code&gt; would be the value &lt;code&gt;foo.txt&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;From here we can now echo the file name using &lt;code&gt;$&amp;lt;&lt;/code&gt;, which gives us the first dependency in the list (of which we only have one anyway).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now here is the second alternative:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;my_list = $(wildcard *.txt)&#xA;print_list: $(my_list)&#xA;.PHONY: $(my_list)&#xA;$(my_list):&#xA;  @echo &amp;quot;Text File:&amp;quot; $@&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, let’s take a moment to break this down so we understand how it works:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Like the first alternative, we retrieve the list of files using the &lt;code&gt;wildcard&lt;/code&gt; function. The difference now is that we don’t need to create a copy of the list and modify the names.&lt;/li&gt;&#xA;&lt;li&gt;Next we create a target called &lt;code&gt;print_list&lt;/code&gt; and we set its dependencies to be the &lt;code&gt;my_list&lt;/code&gt; list of file names (e.g. &lt;code&gt;foo.txt bar.txt baz.txt&lt;/code&gt;). As we mentioned before, there are no such targets defined in our Makefile.&lt;/li&gt;&#xA;&lt;li&gt;The next step is to define a &lt;code&gt;.PHONY&lt;/code&gt; target. We do this because in the subsequent step we define a virtual rule, but we don’t specify any prerequisites. This means as we have actual files in our directory that match the potential target name, the rule will never be executed unless we specify it as being &lt;code&gt;.PHONY&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Now we define our virtual rule and we use the &lt;code&gt;$@&lt;/code&gt; to print the name of the file when we execute &lt;code&gt;make print_list&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;includes&#34;&gt;Includes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Make allows you to import more Make specific-functionality via its &lt;code&gt;include&lt;/code&gt; statement. If you create a file with a &lt;code&gt;.mk&lt;/code&gt; extension then that file’s Make related code can be included in your running Makefile. The following example demonstrates how it works:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;include foo.mk # assuming you have a foo.mk file in your project directory&#xA;&#xA;included_stuff:&#xA;    @echo $(my_included_foo)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above example relies on a &lt;code&gt;foo.mk&lt;/code&gt; file containing the following Make contents:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;my_included_foo := hi from the foo include&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When we run &lt;code&gt;make included_stuff&lt;/code&gt;, we see &lt;code&gt;hi from the foo include&lt;/code&gt; printed out.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;include&lt;/code&gt; statement can also be written with a hyphen prefix like so &lt;code&gt;-include&lt;/code&gt;, which means if there is an error loading the specified file then that error is ignored.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We’ve barely even scratched the surface of what’s possible using Make, but hopefully this introduction has piqued your interest in learning more by either reading the GNU Make manual or picking up a book on the subject. I am myself only beginning my investigation into replacing my existing build tools with Make.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s been part of my journey to rediscover original Unix tools that have stood the test of time (for good reason) rather than picking up the new shiny thing which is often nothing more than a slightly modernized abstraction built for people who want to avoid the terminal/shell environment – somewhere I’ve become much more comfortable working the past couple of years.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/building-systems-with-make/</guid>
      <link>https://www.integralist.co.uk/posts/building-systems-with-make/</link>
      <pubDate>Wed, 07 Oct 2015 00:00:00 +0000</pubDate>
      <title>Building Systems With Make</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The purpose of this post is to demonstrate how to configure nginx to use client certificates for authenticated access to your back-end service (in this example: a Ruby/Sinatra application).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the focus of this post isn&amp;rsquo;t about Ruby/Sinatra so don&amp;rsquo;t worry if your back-end service is built with another programming language&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I won&amp;rsquo;t be going into the details of how most of it was set-up, as the majority of this was already documented in a previous blog post here: &lt;a href=&#34;/posts/docker-nginx/&#34;&gt;Setting up nginx with Docker&lt;/a&gt; so I recommend reading through that first if you&amp;rsquo;re new to Docker and nginx.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I will be showing most of the files, but I&amp;rsquo;ll assume you&amp;rsquo;re familiar with nginx and Docker. The changes involved for setting up client authentication is actually very minimal, and in reality the majority of the work is in the creation of a CA, CRL and signing certificates.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you need a refresher on TLS/SSL then please read: &lt;a href=&#34;/posts/security-basics/&#34;&gt;Security basics with GPG, OpenSSH, OpenSSL and Keybase&lt;/a&gt; which covers the SSL handshake process and a lot more.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s get started&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;directory-structure&#34;&gt;Directory Structure&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First things first, we&amp;rsquo;re going to need the following set of files and folders:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── docker-app&#xA;│   ├── Dockerfile&#xA;│   ├── Gemfile&#xA;│   ├── Gemfile.lock&#xA;│   ├── app.rb&#xA;├── docker-nginx&#xA;│   ├── Dockerfile&#xA;│   ├── certs&#xA;│   │   ├── ca.crt&#xA;│   │   ├── ca.key&#xA;│   │   ├── client.crt&#xA;│   │   ├── client.csr&#xA;│   │   ├── client.key&#xA;│   │   ├── server.crt&#xA;│   │   ├── server.csr&#xA;│   │   ├── server.key&#xA;│   └── nginx.conf&#xA;└── html&#xA;    ├── index.html&#xA;    └── test.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can get most of this structure from the following GitHub repository: &lt;a href=&#34;https://github.com/Integralist/Docker-Examples/tree/master/Nginx-ClientCertAccess&#34; target=&#34;_blank&#34;&gt;Integralist/Docker-Examples/Nginx-ClientCertAccess&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I say &amp;ldquo;most&amp;rdquo; because the &lt;code&gt;docker-nginx/certs&lt;/code&gt; folder no longer exists in the repo. This is OK because I&amp;rsquo;ll demonstrate how to generate these files in the following sub sections of this article.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason the &lt;code&gt;docker-nginx/certs&lt;/code&gt; folder no longer exists is due to the last portion of this article where by we switch to another format for generating certificates and self-signing (specifically the &amp;ldquo;&lt;a href=&#34;#7&#34;&gt;Revocation/CRL Management&lt;/a&gt;&amp;rdquo; section).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As far as configuration is concerned, the main part comes down to the &lt;code&gt;nginx.conf&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;user nobody nogroup;&#xA;worker_processes auto;&#xA;&#xA;events {&#xA;  worker_connections 512;&#xA;}&#xA;&#xA;http {&#xA;  upstream app {&#xA;    server app:4567;&#xA;  }&#xA;&#xA;  server {&#xA;    listen *:443;&#xA;    ssl on;&#xA;    server_name &amp;quot;&amp;quot;; &#xA;&#xA;    ssl_certificate        /etc/nginx/certs/server.crt;&#xA;    ssl_certificate_key    /etc/nginx/certs/server.key;&#xA;    ssl_client_certificate /etc/nginx/certs/ca.crt;&#xA;    ssl_verify_client      on;&#xA;&#xA;    root /usr/share/nginx/html;&#xA;&#xA;    location /app/ {&#xA;      proxy_pass http://app/;&#xA;      proxy_set_header X-ClientCert-DN $ssl_client_s_dn;&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As we can see we&amp;rsquo;re telling nginx to listen to any interface on port &lt;code&gt;443&lt;/code&gt; (TLS connections) only. We then enable SSL and specify a few different &lt;code&gt;ssl_&lt;/code&gt; settings that direct nginx to certain locations where it can find the server&amp;rsquo;s own certificate and private key, as well as the CA certificate that was used to sign both the server certificate as well as the user/client certificate we&amp;rsquo;ll be using shortly to connect to this service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll probably also notice &lt;code&gt;ssl_verify_client&lt;/code&gt; has been turned &lt;code&gt;on&lt;/code&gt;. This could be made &amp;lsquo;optional&amp;rsquo; so that some connections are allowed to public endpoints. But in my case I want everything to be protected by client certs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, when we proxy traffic onto our back-end service, we also create a new custom HTTP header to be proxied on as well; which I&amp;rsquo;ve named: &lt;code&gt;X-ClientCert-DN&lt;/code&gt;. The value assigned to this custom header uses the nginx &lt;code&gt;$ssl_client_s_dn&lt;/code&gt; variable, which extracts the &lt;code&gt;Common Name&lt;/code&gt; section of the client&amp;rsquo;s certificate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Interestingly, the Ruby server receives the HTTP request with the custom header transformed into &lt;code&gt;HTTP_X_CLIENTCERT_DN&lt;/code&gt;. Just something to be aware of if you decide to switch from Ruby to another programming language, such as &lt;a href=&#34;https://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt; (as your mileage may vary).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;generating-the-certificates-and-keys&#34;&gt;Generating the certificates and keys&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So the first thing we want to do is to create the CA key/certificate, which will be used for signing both the server and the client certificate requests:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl genrsa -des3 -out ca.key 4096&#xA;openssl req -new -x509 -days 365 -key ca.key -out ca.crt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For the &lt;code&gt;ca.crt&lt;/code&gt; generation I pretty much entered &lt;code&gt;.&lt;/code&gt; (which means &amp;lsquo;no value&amp;rsquo;) for all details. The only exception was the &lt;code&gt;Common Name&lt;/code&gt; field which I entered &amp;lsquo;TheCA&amp;rsquo; (so I could recognise it as the &amp;lsquo;ca&amp;rsquo;, just in case I needed to inspect the certificate)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;all of these commands I ran inside of the &lt;code&gt;docker-nginx/certs&lt;/code&gt; folder to make it easier later on to mount them as a volume into my Docker containers&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Next we&amp;rsquo;ll create the server key along with a CSR (Certificate Signing Request) which the CA will use to generate the server&amp;rsquo;s certificate:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl genrsa -out server.key 4096&#xA;openssl req -new -key server.key -out server.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For the CSR I pretty much entered &lt;code&gt;.&lt;/code&gt; (which means &amp;lsquo;no value&amp;rsquo;) for all details. The only exception was the &lt;code&gt;Common Name&lt;/code&gt; field which I entered &amp;lsquo;TheServer&amp;rsquo; (so I recognise it as the &amp;lsquo;server&amp;rsquo;, just in case I needed to inspect the certificate).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I don&amp;rsquo;t specify &lt;code&gt;-des3&lt;/code&gt; in the command as I don&amp;rsquo;t want to generate a passphrase for the private key. If I have to restart my server I don&amp;rsquo;t want the automation to be affected by requiring me to manually enter the passphrase&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now we&amp;rsquo;ll self-sign the server&amp;rsquo;s CSR and generate its own certificate (in case it&amp;rsquo;s not clear: self-signing isn&amp;rsquo;t something you want to do unless you know you are going to ask your users to trust your certificate and ignore big warnings about an unknown CA signing the server&amp;rsquo;s cert):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK, almost there. We now need to create a private key and CSR for our client (i.e. this will be the user trying to access the service):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl genrsa -out client.key 2048&#xA;openssl req -new -key client.key -out client.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice I&amp;rsquo;ve made the encryption length &lt;code&gt;2048&lt;/code&gt; instead of &lt;code&gt;4096&lt;/code&gt;. I did this as a speed/perf compromise, as higher length encryption keys can be slower to use with the TLS handshake process (just one of the many security compromises that need to be considered).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the CSR I pretty much entered &lt;code&gt;.&lt;/code&gt; (which means &amp;lsquo;no value&amp;rsquo;) for all details. The only exceptions were the &lt;code&gt;Common Name&lt;/code&gt; field which I entered &amp;lsquo;Mark McDonnell&amp;rsquo; (so I recognise it as the &amp;lsquo;client&amp;rsquo;) and the &lt;code&gt;Email Address&lt;/code&gt; field, which I entered something like &lt;code&gt;mark@integralist.com&lt;/code&gt; (as I want to parse out that email in my Ruby application)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;again I don&amp;rsquo;t specify &lt;code&gt;-des3&lt;/code&gt; in the command, as I don&amp;rsquo;t want to generate a passphrase for the private key&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Finally, I sign the client CSR using the CA certificate:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s it, that&amp;rsquo;s all the different certificates set-up and ready to be used. Let&amp;rsquo;s move onto building our Docker set-up and running some containers&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;building&#34;&gt;Building&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This section&amp;rsquo;s nice and short because I provide the &lt;code&gt;Dockerfile&lt;/code&gt; for both the Ruby and nginx applications (just make sure you &lt;code&gt;cd ../&lt;/code&gt; back up into the project&amp;rsquo;s root directory before executing the following commands):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t my-ruby-app ./docker-app&#xA;docker build -t my-nginx ./docker-nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;running&#34;&gt;Running&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This section is also nice and short. First let&amp;rsquo;s run the Ruby application:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name ruby-app -p 4567:4567 -d my-ruby-app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s run the nginx container:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name nginx-container \&#xA;  -v $(pwd)/html:/usr/share/nginx/html:ro \&#xA;  -v $(pwd)/docker-nginx/certs/server.crt:/etc/nginx/certs/server.crt \&#xA;  -v $(pwd)/docker-nginx/certs/server.key:/etc/nginx/certs/server.key \&#xA;  -v $(pwd)/docker-nginx/certs/ca.crt:/etc/nginx/certs/ca.crt \&#xA;  -v $(pwd)/docker-nginx/nginx.conf:/etc/nginx/nginx.conf:ro \&#xA;  --link ruby-app:app \&#xA;  -P -d my-nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;OK so the nginx &lt;code&gt;docker run&lt;/code&gt; command was a little bit more involved, but really all it&amp;rsquo;s doing is mounting volumes from the host machine (my Mac) into the Docker container. The most important items to be aware of are the certs we&amp;rsquo;re mounting into the container as well as the &lt;code&gt;nginx.conf&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also notice I&amp;rsquo;m linking the running Ruby container to the nginx container. This is important because it allows nginx to utilise the Ruby container as a back-end service.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;verifying&#34;&gt;Verifying&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now the containers are built and running, we should verify that the services themselves are doing what they should be. But before we do that, it&amp;rsquo;s worth me mentioning now that when I reference &lt;code&gt;&amp;lt;ip&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;nginx_port&amp;gt;&lt;/code&gt; below, you&amp;rsquo;ll need to swap these references for actual values.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To get the value for &lt;code&gt;&amp;lt;ip&amp;gt;&lt;/code&gt; I&amp;rsquo;m using the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$(docker-machine ip dev)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This gives me the ip address of my running docker VM. If you&amp;rsquo;re running on Linux then localhost &lt;code&gt;127.0.0.1&lt;/code&gt; would suffice. But as you can see, I&amp;rsquo;m running things on a Mac and so I&amp;rsquo;m using &lt;code&gt;docker-machine&lt;/code&gt; with a VM named &lt;code&gt;dev&lt;/code&gt;. Your mileage will ultimately vary.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To get the value of &lt;code&gt;&amp;lt;nginx_port&amp;gt;&lt;/code&gt; I&amp;rsquo;m using the following to access the dynamically allocated port number:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$(docker port nginx-container 443 | awk -F &#39;:&#39; &#39;{ print $2 }&#39;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where &lt;code&gt;nginx-container&lt;/code&gt; is the name I gave to my container when executing the &lt;code&gt;docker run&lt;/code&gt; command earlier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s demonstrate some different application routes that should all &lt;strong&gt;FAIL&lt;/strong&gt; (for reasons I&amp;rsquo;ll explain as we go along):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So in the above example, we should see the following error, as the HTTP protocol was used instead of HTTPS (remember that nginx was setup to only listen on 443, not 80):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;400 The plain HTTP request was sent to HTTPS port&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body bgcolor=&amp;quot;white&amp;quot;&amp;gt;&#xA;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;400 Bad Request&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&#xA;&amp;lt;center&amp;gt;The plain HTTP request was sent to HTTPS port&amp;lt;/center&amp;gt;&#xA;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx/1.4.6 (Ubuntu)&amp;lt;/center&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s try and switch to HTTPS:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above attempt should also error, as the server&amp;rsquo;s cert isn&amp;rsquo;t trusted (i.e. it&amp;rsquo;s self-signed). To fix this we can use the &lt;code&gt;--insecure&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl --insecure https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The above attempt should now fail because no client certificate was provided for purpose of authentication with nginx. Great. So now we&amp;rsquo;re verified all the failing paths, let&amp;rsquo;s consider &lt;code&gt;curl&lt;/code&gt; commands that should return us some actual working content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But before we do that, a slight intermission&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h3 id=&#34;mac-os-x-curl&#34;&gt;Mac OS X Curl&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the below section I&amp;rsquo;ll be demonstrating some &lt;code&gt;curl&lt;/code&gt; calls that actually &lt;em&gt;work&lt;/em&gt;. Now you might still find they don&amp;rsquo;t work for you, but not for the reasons you&amp;rsquo;d expect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem depends on what operating system you&amp;rsquo;re playing along with. For example, if you see the following error&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl: (58) SSL: Can&#39;t load the certificate &amp;quot;/path/to/docker-nginx/certs/client.crt&amp;quot; and its private key: OSStatus -25299&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;then fear not, it&amp;rsquo;s just that the &lt;code&gt;curl&lt;/code&gt; command provided by Mac OS X is a bit rubbish. The solution is to use Docker to run a different version of &lt;code&gt;curl&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run -it speg03/curl &amp;lt;...&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll use this Docker container like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run \&#xA;  -it \&#xA;  -v $(pwd)/docker-nginx/certs/client.key:/var/cert/client.key \&#xA;  -v $(pwd)/docker-nginx/certs/client.crt:/var/cert/client.crt \&#xA;  speg03/curl --insecure \&#xA;              --key /var/cert/client.key \&#xA;              --cert /var/cert/client.crt \&#xA;              https://$(docker-machine ip dev):$(docker port nginx-container 443 | awk -F &#39;:&#39; &#39;{ print $2 }&#39;)/app/cert&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Yeah it&amp;rsquo;s bit long-winded, but you can alias bits or stick it into a bash function if you prefer. Effectively we&amp;rsquo;re mounting our generated certificates into the container and then specifying them as &lt;code&gt;--key&lt;/code&gt; and &lt;code&gt;--cert&lt;/code&gt; when trying to access a specific application endpoint.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the following &lt;code&gt;curl&lt;/code&gt; commands just remember to use the Dockerised version of &lt;code&gt;curl&lt;/code&gt; if you&amp;rsquo;re finding your native Mac OS X &lt;code&gt;curl&lt;/code&gt; isn&amp;rsquo;t working for you.&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;Now in the following section I define some local variables for the purpose of making the overall &lt;code&gt;curl&lt;/code&gt; commands shorter. But all of these &lt;code&gt;curl&lt;/code&gt; requests should work fine (as the client cert/key have been provided as flags):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;client_key=$(pwd)/docker-nginx/certs/client.key&#xA;client_crt=$(pwd)/docker-nginx/certs/client.crt&#xA;&#xA;curl --insecure --key $client_key --cert $client_crt https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/&#xA;curl --insecure --key $client_key --cert $client_crt https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/test.html&#xA;curl --insecure --key $client_key --cert $client_crt https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/app/&#xA;curl --insecure --key $client_key --cert $client_crt https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/app/foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we use &lt;code&gt;--insecure&lt;/code&gt; to trust the self-signed certificate, we could install the CA into our OS certificate store but I&amp;rsquo;ve not done that as this is just an example set-up and so I&amp;rsquo;m using &lt;code&gt;--insecure&lt;/code&gt; as a quick win&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Finally, let&amp;rsquo;s test the client cert is being proxied through the HTTP request to the Ruby app:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl --insecure --key $client_key --cert $client_crt https://&amp;lt;ip&amp;gt;:&amp;lt;nginx_port&amp;gt;/app/cert&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should see something like the following output by the Ruby application:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/CN=Mark McDonnell/emailAddress=mark@integralist.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now at this point you can parse your client certificate&amp;rsquo;s CommonName (CN) however you like. In my application I just print it back out to the user, but in a real-world application you might want to use the details to present some nice personalised welcome message like &amp;ldquo;Hello Mark!&amp;rdquo; or whatever.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Either way, you can only access the Ruby application if you provide a cert/key that was signed by the self-signed CA that is specified in the nginx configuration.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you were to try and provide a different cert/key (one that wasn&amp;rsquo;t signed by the self-signed CA), then you&amp;rsquo;ll see the following error response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;400 The SSL certificate error&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body bgcolor=&amp;quot;white&amp;quot;&amp;gt;&#xA;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;400 Bad Request&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&#xA;&amp;lt;center&amp;gt;The SSL certificate error&amp;lt;/center&amp;gt;&#xA;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx/1.4.6 (Ubuntu)&amp;lt;/center&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which is great. That is exactly what we want to see: denying access to our service unless properly authorised.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;revocation&#34;&gt;Revocation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now before we close, we should consider what happens when we want to prevent a user from accessing our content after we have issued them a certificate. In order to do this we need to provide a CRL (Certificate Revocation List) to nginx. The purpose of the CRL is to identify which certificates issued by the CA have since been revoked and should no longer allow access to the service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The modification we need to make to nginx is simple:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssl_certificate        /etc/nginx/certs/server.crt;&#xA;ssl_certificate_key    /etc/nginx/certs/server.key;&#xA;ssl_client_certificate /etc/nginx/certs/ca.crt;&#xA;ssl_verify_client      on;&#xA;ssl_crl                /etc/nginx/certs/crl.pem;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice where we defined all the other &lt;code&gt;ssl_&lt;/code&gt; configuration, we have now added &lt;code&gt;ssl_crl&lt;/code&gt; at the bottom and pointed it to a &lt;code&gt;crl.pem&lt;/code&gt; file that contains the list of revoked certificates.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;use &lt;code&gt;service nginx reload&lt;/code&gt; to cause nginx to pick up any changes to the &lt;code&gt;crl.pem&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;crl-management&#34;&gt;CRL Management&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;At this point in time we have a working set-up. I&amp;rsquo;m now going to change things by no longer using the &lt;code&gt;docker-nginx/certs&lt;/code&gt; folder we&amp;rsquo;ve been using so far. I&amp;rsquo;m going to start from scratch in that respect, in order to demonstrate how CRL (Certificate Revocation Lists) work and how to create a set-up that allows you to manage a CRL.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s begin by removing the &lt;code&gt;docker-nginx/certs&lt;/code&gt; folder and creating a new directory within &lt;code&gt;docker-nginx&lt;/code&gt; called &lt;code&gt;CertificateManagement&lt;/code&gt;. Once you&amp;rsquo;ve created that folder &lt;code&gt;cd&lt;/code&gt; into it (as all the following commands will need to be run from within that directory - unless I say otherwise).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;openssl-cnf&#34;&gt;Openssl.cnf&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We need to create an &lt;code&gt;openssl.cnf&lt;/code&gt; file, which will allow us to automate a lot of the generic set-up that you would otherwise have to manually specify yourself via the command-line (&lt;code&gt;touch openssl.cnf&lt;/code&gt; should do the trick). The contents of this file will be as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#&#xA;# OpenSSL configuration file.&#xA;#&#xA;&#xA;# Establish working directory.&#xA;dir            = .&#xA;&#xA;[ ca ]&#xA;default_ca     = CA_default&#xA;&#xA;[ CA_default ]&#xA;serial           = $dir/serial&#xA;database         = $dir/certindex.txt&#xA;new_certs_dir    = $dir/certs&#xA;certificate      = $dir/ca.crt&#xA;private_key      = $dir/private/ca.key&#xA;default_days     = 365&#xA;default_md       = md5&#xA;default_crl_days = 30&#xA;preserve         = no&#xA;email_in_dn      = yes&#xA;nameopt          = default_ca&#xA;certopt          = default_ca&#xA;policy           = policy_match&#xA;crl_dir          = $dir/revoked&#xA;crlnumber        = $crl_dir/crlnumber&#xA;crl_extensions   = crl_ext&#xA;x509_extensions  = usr_cert&#xA;copy_extensions  = copy&#xA;&#xA;[ policy_match ]&#xA;countryName            = match    # Must be the same as the CA&#xA;stateOrProvinceName    = optional # not required&#xA;organizationName       = optional # not required&#xA;organizationalUnitName = optional # not required&#xA;commonName             = supplied # must be there, whatever it is&#xA;emailAddress           = supplied # must be there, whatever it is&#xA;&#xA;[ crl_ext ]&#xA;authorityKeyIdentifier = keyid:always,issuer:always&#xA;&#xA;[ usr_cert ]&#xA;basicConstraints       = CA:FALSE&#xA;subjectKeyIdentifier   = hash&#xA;authorityKeyIdentifier = keyid, issuer&#xA;crlDistributionPoints  = URI:http://www.yourdomain.com/ca/crl.pem # this should be updated to be unique to the CA&#xA;&#xA;[ req ]&#xA;default_bits       = 2048    # Size of keys&#xA;default_keyfile    = key.pem # name of generated keys&#xA;default_md         = md5     # message digest algorithm&#xA;string_mask        = nombstr # permitted characters&#xA;distinguished_name = req_distinguished_name&#xA;req_extensions     = v3_req&#xA;&#xA;[ req_distinguished_name ]&#xA;# Variable name                Prompt string&#xA;#-------------------------      ----------------------------------&#xA;0.organizationName     = Organization Name (company)&#xA;organizationalUnitName = Organizational Unit Name (department, division)&#xA;emailAddress           = Email Address&#xA;emailAddress_max       = 40&#xA;localityName           = Locality Name (city, district)&#xA;stateOrProvinceName    = State or Province Name (full name)&#xA;countryName            = Country Name (2 letter code)&#xA;countryName_min        = 2&#xA;countryName_max        = 2&#xA;commonName             = Common Name (hostname, IP, or your name)&#xA;commonName_max         = 64&#xA;&#xA;# Default values for the above, for consistency and less typing.&#xA;# Variable name                Value&#xA;#------------------------      ------------------------------&#xA;0.organizationName_default  = My Company&#xA;localityName_default        = My Town&#xA;stateOrProvinceName_default = State or Providence&#xA;countryName_default         = US&#xA;&#xA;[ v3_ca ]&#xA;basicConstraints            = CA:TRUE&#xA;subjectKeyIdentifier        = hash&#xA;authorityKeyIdentifier      = keyid:always,issuer:always&#xA;&#xA;[ v3_req ]&#xA;basicConstraints            = CA:FALSE&#xA;subjectKeyIdentifier        = hash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for an excellent walk-through of the &lt;code&gt;openssl.conf&lt;/code&gt; and what it all means, then I highly recommend reading &lt;a href=&#34;https://www.phildev.net/ssl/opensslconf.html&#34; target=&#34;_blank&#34;&gt;phildev.net/ssl/opensslconf&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;From here we now want to create some other directories referenced by &lt;code&gt;openssl.cnf&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;mkdir certs private revoked&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We need to create a few files which are also referenced by &lt;code&gt;openssl.cnf&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &#39;100001&#39; &amp;gt; serial&#xA;touch certindex.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now we should find we have the following tree structure (inside of &lt;code&gt;docker-nginx/CertificateManagement&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── certindex.txt&#xA;├── certs&#xA;├── openssl.cnf&#xA;├── private&#xA;├── revoked&#xA;└── serial&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;generating-a-new-ca&#34;&gt;Generating a new CA&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll be recreating a CA certificate that&amp;rsquo;s valid for a year (along with its private key). The &lt;code&gt;ca.crt&lt;/code&gt; file that will be generated is what can be provided to users for importing into their web browsers so that the CA becomes a trusted entity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now create the CA:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl req -new -x509 -days 365 -out ca.crt -keyout private/ca.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Most of the details I was asked for I left blank, with the exception of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;PEM pass phrase&lt;/code&gt; which I set to &lt;code&gt;pass&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Country Name&lt;/code&gt; which I set to &lt;code&gt;GB&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Organization Name&lt;/code&gt; which I set to &lt;code&gt;Integralist Ltd&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Common Name&lt;/code&gt; which I set to &lt;code&gt;Integralist&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Email Address&lt;/code&gt; which I set to &lt;code&gt;ca@integralist.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;At this point our directory tree should look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── ca.crt          # newly created&#xA;├── certindex.txt&#xA;├── certs&#xA;├── openssl.cnf&#xA;├── private&#xA;│   └── ca.key      # newly created&#xA;├── revoked&#xA;└── serial&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;server-csr&#34;&gt;Server CSR&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll now recreate our server CSR (Certificate Signing Request) and private key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl req -new -nodes -out server.csr -keyout private/server.key -config ./openssl.cnf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Most of the details I was asked for I left blank, with the exception of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Email Address&lt;/code&gt; which I set to &lt;code&gt;server@integralist.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Country Name&lt;/code&gt; which I set to &lt;code&gt;GB&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Common Name&lt;/code&gt; which I set to &lt;code&gt;TheServer&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;At this point our directory tree should look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── ca.crt&#xA;├── certindex.txt&#xA;├── certs&#xA;├── openssl.cnf&#xA;├── private&#xA;│   ├── ca.key&#xA;│   └── server.key # newly created&#xA;├── revoked&#xA;├── serial&#xA;└── server.csr     # newly created&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;server-cert&#34;&gt;Server Cert&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll now sign our server&amp;rsquo;s CSR like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl ca -out server.crt -config ./openssl.cnf -infiles server.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll be prompted to enter the pass phrase for the CA and then it&amp;rsquo;ll display information about the new server certificate and if you&amp;rsquo;re happy for it to be generated:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Using configuration from ./openssl.cnf&#xA;Enter pass phrase for ./private/ca.key:&#xA;Check that the request matches the signature&#xA;Signature ok&#xA;The Subject&#39;s Distinguished Name is as follows&#xA;emailAddress          :IA5STRING:&#39;server@integralist.com&#39;&#xA;countryName           :PRINTABLE:&#39;GB&#39;&#xA;commonName            :PRINTABLE:&#39;TheServer&#39;&#xA;Certificate is to be certified until Oct  2 14:14:23 2016 GMT (365 days)&#xA;&#xA;Sign the certificate? [y/n]: y&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;After this it&amp;rsquo;ll ask if you want to commit the changes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;1 out of 1 certificate requests certified, commit? [y/n] y&#xA;Write out database with 1 new entries&#xA;Data Base Updated&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you look at the &lt;code&gt;serial&lt;/code&gt; file you&amp;rsquo;ll notice its value is now &lt;code&gt;100002&lt;/code&gt; (we created it with the initial value of &lt;code&gt;100001&lt;/code&gt;) and that there is now a &lt;code&gt;serial.old&lt;/code&gt; which contains the previous value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you look at the &lt;code&gt;certindex.txt&lt;/code&gt; you&amp;rsquo;ll see a new record has been added (it wont be identical, but it&amp;rsquo;ll look something like the following):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;V 161002141423Z   100001  unknown /C=GB/CN=TheServer/emailAddress=server@integralist.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the number &lt;code&gt;100001&lt;/code&gt;. This is the serial number (and name) of the certificate that&amp;rsquo;s been generated for the server and is used for the purpose of revoking the certificate at a later date (e.g. if the private key becomes compromised).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At this point our directory tree should look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── ca.crt&#xA;├── certindex.txt      # updated&#xA;├── certindex.txt.attr # newly created&#xA;├── certindex.txt.old  # newly created&#xA;├── certs&#xA;│   └── 100001.pem     # newly created&#xA;├── openssl.cnf&#xA;├── private&#xA;│   ├── ca.key&#xA;│   └── server.key&#xA;├── revoked&#xA;├── serial             # updated&#xA;├── serial.old         # newly created&#xA;├── server.crt         # newly created&#xA;└── server.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;client-cert&#34;&gt;Client Cert&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Same as before with the server, we&amp;rsquo;ll want to recreate the client CSR and private key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl req -new -nodes -out client.csr -keyout private/client.key -days 365 -config ./openssl.cnf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Most of the details I was asked for I left blank, with the exception of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Email Address&lt;/code&gt; which I set to &lt;code&gt;client@integralist.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Country Name&lt;/code&gt; which I set to &lt;code&gt;GB&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Common Name&lt;/code&gt; which I set to &lt;code&gt;TheClient&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;At this point our directory tree should look like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── ca.crt&#xA;├── certindex.txt&#xA;├── certindex.txt.attr&#xA;├── certindex.txt.old&#xA;├── certs&#xA;│   └── 100001.pem&#xA;├── client.csr         # newly created&#xA;├── instructions.md&#xA;├── openssl.cnf&#xA;├── private&#xA;│   ├── ca.key&#xA;│   ├── client.key     # newly created&#xA;│   └── server.key&#xA;├── revoked&#xA;├── serial&#xA;├── serial.old&#xA;├── server.crt&#xA;└── server.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Typically you&amp;rsquo;ll get a request from a company employee or customer that needs access to your service(s) and so that&amp;rsquo;s when you&amp;rsquo;ll issue them a client certificate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here we can self-sign the certificate (just like we did with the server CSR):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl ca -out client.crt -days 365 -config ./openssl.cnf -infiles client.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The exact same process is required as before when signing the server certificate, so all the same files are updated (e.g. &lt;code&gt;serial&lt;/code&gt; and &lt;code&gt;certindex.txt&lt;/code&gt;) and similar new files are created:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── ca.crt&#xA;├── certindex.txt&#xA;├── certindex.txt.attr&#xA;├── certindex.txt.attr.old&#xA;├── certindex.txt.old&#xA;├── certs&#xA;│   ├── 100001.pem&#xA;│   └── 100002.pem         # newly created&#xA;├── client.crt             # newly created&#xA;├── client.csr&#xA;├── instructions.md&#xA;├── openssl.cnf&#xA;├── private&#xA;│   ├── ca.key&#xA;│   ├── client.key&#xA;│   └── server.key&#xA;├── revoked&#xA;├── serial&#xA;├── serial.old&#xA;├── server.crt&#xA;└── server.csr&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;crl-certificate-revocation-list&#34;&gt;CRL (Certificate Revocation List)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At this point we need to look at how to generate a revocation list, as that list will be provided to nginx so it can cross-reference the incoming certificate against it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first thing we need to do is to add an initial number to a &lt;code&gt;crlnumber&lt;/code&gt; file into our &lt;code&gt;revoked&lt;/code&gt; directory we created at the beginning of this section on CRL management:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo 01 &amp;gt; ./revoked/crlnumber&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This file is used by the CRL in a way similar to how the CA uses the &lt;code&gt;serial&lt;/code&gt; file. By that I mean, every time you revoke a certificate you&amp;rsquo;ll need to generate a new CRL (using the below command). Every new CRL you create will include the current &lt;code&gt;crlnumber&lt;/code&gt; (which we&amp;rsquo;ll see in a moment, after we create a CRL and then inspect it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once we have the &lt;code&gt;crlnumber&lt;/code&gt; file created (and an initial value added) we can then run the following command to generate our first CRL:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl ca -gencrl -out revoked/crl.pem -config ./openssl.cnf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to inspect the CRL file to see what&amp;rsquo;s inside, then run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl crl -text -noout -in revoked/crl.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;-noout&lt;/code&gt; simply prevents the x509 CRL hash from being printed as well (which is what you would have seen if you had just run &lt;code&gt;cat revoked/crl.pem&lt;/code&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The command will output something that looks like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Certificate Revocation List (CRL):&#xA;        Version 2 (0x1)&#xA;        Signature Algorithm: md5WithRSAEncryption&#xA;        Issuer: /C=GB/O=IntegralistLtd/CN=Integralist/emailAddress=ca@integralist.com&#xA;        Last Update: Oct  3 14:45:53 2015 GMT&#xA;        Next Update: Nov  2 14:45:53 2015 GMT&#xA;        CRL extensions:&#xA;            X509v3 Authority Key Identifier: &#xA;                keyid:43:3A:75:41:E1:AE:46:F0:5F:AC:F4:24:6A:3A:DB:D1:31:7E:27:6B&#xA;                DirName:/C=GB/O=IntegralistLtd/CN=Integralist/emailAddress=ca@integralist.com&#xA;                serial:E0:86:88:E8:CA:0C:7F:29&#xA;&#xA;            X509v3 CRL Number: &#xA;                1&#xA;No Revoked Certificates.&#xA;    Signature Algorithm: md5WithRSAEncryption&#xA;        28:1d:b0:f3:fb:69:f0:1a:36:83:2d:38:50:72:c6:11:39:4f:&#xA;        6d:e9:da:0a:ec:63:a9:b1:63:55:ff:79:48:4f:9e:6a:ec:c3:&#xA;        2e:01:88:ea:aa:8d:76:12:ac:f9:0b:77:d3:aa:dd:c4:22:bd:&#xA;        fe:77:5d:a2:2b:3b:e9:22:b5:32:2e:26:74:1c:6c:94:78:84:&#xA;        08:54:44:52:87:f2:51:68:98:e7:7c:42:cd:44:f6:6b:4c:28:&#xA;        b0:d5:11:4a:49:4d:4f:83:09:f3:6b:2d:69:a3:95:d5:55:e0:&#xA;        dc:4c:fd:53:5c:78:5e:a6:48:ac:7d:66:c8:20:6b:ba:c7:19:&#xA;        37:ba&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can tell how many versions of the CRL have been generated by looking at the value assigned to &lt;code&gt;X509v3 CRL Number&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The CRL itself has been configured (by the &lt;code&gt;openssl.conf&lt;/code&gt;) to expire after 30 days. So even if you don&amp;rsquo;t revoke any certificates in that time, you&amp;rsquo;ll still want to regenerate the CRL. Meaning there needs to be a certain level of automation involved (which is outside the scope of this article).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;re-running-our-containers&#34;&gt;Re-running our containers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK, we&amp;rsquo;ve now regenerated our CA, server and client certificates and we&amp;rsquo;ve also looked at creating a CRL; so we&amp;rsquo;ll want to stop the currently running nginx container (using a combination of &lt;code&gt;docker ps&lt;/code&gt; to find the container id, along with &lt;code&gt;docker stop &amp;lt;cid&amp;gt;&lt;/code&gt; and &lt;code&gt;docker rm &amp;lt;cid&amp;gt;&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s first jump back up to our project root directory (&lt;code&gt;cd ../../&lt;/code&gt;) and restart the nginx container, but this time using the new certificates (this will also mean our updated &lt;code&gt;nginx.conf&lt;/code&gt; file will be pulled in).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the new &lt;code&gt;docker run&lt;/code&gt; command we&amp;rsquo;ll be using is a bit of a monster! Lots of mounted volumes&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run \&#xA;  --name nginx-container \&#xA;  -v $(pwd)/html:/usr/share/nginx/html:ro \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/server.crt:/etc/nginx/certs/server.crt \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/private/server.key:/etc/nginx/certs/server.key \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/ca.crt:/etc/nginx/certs/ca.crt \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/revoked/crl.pem:/etc/nginx/certs/crl.pem \&#xA;  -v $(pwd)/docker-nginx/nginx.conf:/etc/nginx/nginx.conf:ro \&#xA;  --link ruby-app:app -P -d my-nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can now verify that nginx is working as expected; and by that I mean: our client (when using the provided client certificate) can access the Ruby service:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run \&#xA;  -it \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/private/client.key:/var/cert/client.key \&#xA;  -v $(pwd)/docker-nginx/CertificateManagement/client.crt:/var/cert/client.crt \&#xA;  speg03/curl --insecure \&#xA;              --key /var/cert/client.key \&#xA;              --cert /var/cert/client.crt \&#xA;              https://$(docker-machine ip dev):$(docker port nginx-container 443 | awk -F &#39;:&#39; &#39;{ print $2 }&#39;)/app/cert&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This gives us the output as expected:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/C=GB/CN=TheClient/emailAddress=client@integralist.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;revoking-certificates&#34;&gt;Revoking Certificates&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here we are at our final stage. We&amp;rsquo;ve verified that the client certificates are working using the new format. We&amp;rsquo;ve created a CRL and so far the client cert has been allowed through nginx.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What we&amp;rsquo;ll do now is revoke that certificate and then re-run our nginx container to see if it has picked up the new CRL and subsequently recognises that the client cert is no longer valid (and so refuse access to the Ruby service).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to revoke the client certificate, I first need to look it up in the &lt;code&gt;certindex.txt&lt;/code&gt; file. The contents of that file resembles something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;V 161002113732Z 100001 unknown /C=GB/CN=TheServer/emailAddress=server@integralist.com&#xA;V 161002113931Z 100002 unknown /C=GB/CN=TheClient/emailAddress=client@integralist.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I can now easily say to myself &amp;ldquo;ok, so I know its the &amp;lsquo;client&amp;rsquo; who needs their cert revoked; that looks to be cert 100002&amp;rdquo;, and from there I would execute the following command (make sure you &lt;code&gt;cd&lt;/code&gt; into the &lt;code&gt;docker-nginx/CertificateManagement/&lt;/code&gt; directory before running the next command):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl ca -revoke certs/100002.pem -config ./openssl.cnf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will output the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Using configuration from ./openssl.cnf&#xA;Enter pass phrase for ./private/ca.key:&#xA;Revoking Certificate 100002.&#xA;Data Base Updated&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if we look at the &lt;code&gt;certindex.txt&lt;/code&gt; file again we&amp;rsquo;ll see that &lt;code&gt;100002&lt;/code&gt; has been revoked:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;V 161002113732Z               100001 unknown /C=GB/CN=TheServer/emailAddress=server@integralist.com&#xA;R 161002113931Z 151003114104Z 100002 unknown /C=GB/CN=TheClient/emailAddress=client@integralist.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice the &lt;code&gt;R&lt;/code&gt; for &amp;ldquo;revoked&amp;rdquo; has been applied. The additional reference number &lt;code&gt;151003114104Z&lt;/code&gt; is the revocation timestamp and you can see the full format &lt;a href=&#34;http://pki-tutorial.readthedocs.io/en/latest/cadb.html&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;as you can see, to revoke a certificate means you need to keep copies of all certificates that have been generated&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So now the client cert has been revoked, let&amp;rsquo;s generate a new CRL and then apply that to the nginx container.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ca -gencrl -out revoked/crl.pem -config ./openssl.cnf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now verify the version number inside the &lt;code&gt;crl.pem&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl crl -text -noout -in revoked/crl.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You should now see &lt;code&gt;X509v3 CRL Number&lt;/code&gt; has a value of &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now stop the running nginx container, and re-run it so it can pick up the new CRL (use same commands as before, but remember to move up to the project root - &lt;code&gt;cd ../../&lt;/code&gt; - before you do so).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when you try to access the &lt;code&gt;/app/cert&lt;/code&gt; endpoint you&amp;rsquo;ll find that you cannot:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;400 The SSL certificate error&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body bgcolor=&amp;quot;white&amp;quot;&amp;gt;&#xA;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;400 Bad Request&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&#xA;&amp;lt;center&amp;gt;The SSL certificate error&amp;lt;/center&amp;gt;&#xA;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx/1.4.6 (Ubuntu)&amp;lt;/center&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Job done.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://nginx.org/en/docs/http/ngx_http_ssl_module.html&#34; target=&#34;_blank&#34;&gt;nginx http ssl module&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.mad-hacking.net/documentation/linux/security/ssl-tls/creating-ca.xml&#34; target=&#34;_blank&#34;&gt;mad-hacking.net/ssl-tls&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.phildev.net/ssl/opensslconf.html&#34; target=&#34;_blank&#34;&gt;Openssl.conf Walkthru&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many side effects and issues we&amp;rsquo;ve not covered, such as: how to handle multiple CRLs (generated from different CA&amp;rsquo;s). This is a problem where by nginx&amp;rsquo;s &lt;code&gt;ssl_crl&lt;/code&gt; setting only allows you to point to a single CRL &amp;ldquo;file&amp;rdquo; (rather than a directory of CRLs). To work around this issue you would need to concatenate all your CRLs together into a single file (which is a bit of a pain).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is also the question of automation. This is a process that is fraught with user error and mistakes and so ideally you&amp;rsquo;d want to automate as much of the CRL and certificate generating process as possible. I&amp;rsquo;ll leave this as an exercise for the reader.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In closing: hopefully you&amp;rsquo;ve found the information in this article useful and it has helped you to understand some of the more complicated processes for handling certificate authentication.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/client-cert-authentication/</guid>
      <link>https://www.integralist.co.uk/posts/client-cert-authentication/</link>
      <pubDate>Sat, 03 Oct 2015 00:00:00 +0000</pubDate>
      <title>Client Cert Authentication</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;dns-domain-name-system&#34;&gt;DNS (Domain Name System)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You likely have many applications running on your laptop right now, and chances are some of them require an external resource or piece of data that will be retrieved from across a network.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for your applications to access these resources they need to know their location. The location is typically identified by an ip address and are written in either decimal or hexadecimal.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When dealing with ips, they can be very hard to memorise; especially as there are two different forms of ip:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/IPv4&#34; target=&#34;_blank&#34;&gt;IPv4&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/IPv6&#34; target=&#34;_blank&#34;&gt;IPv6&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;An IPv4 identifier is 32 bits long, written in decimal and separated by periods:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;74.125.224.72&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An IPv6 identifier is 128 bits long, written in hexadecimal and separated by colons:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;3ffe:1900:4545:3:200:f8ff:fe21:67cf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s even more awkward if you have a program with a hard coded ip address for a specific resource. If the resource has to change its location, then the program now has to be updated as well to point to that new location.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&amp;rsquo;s easier would be the use of a name that maps to an underlying value. So for example, the ip address &lt;code&gt;74.125.224.72&lt;/code&gt; points to Google&amp;rsquo;s search page. Rather than type that ip into your web browser (or hard code it inside an application) you would likely instead find it much easier to reference the resource by its name: &lt;code&gt;google.com&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Your application (e.g. web browser, whatever) when encountering this &amp;lsquo;resource&amp;rsquo; will lookup the name provided, resolve the underlying ip address and ultimately retrieve the relevant resource.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the basis of what is known as DNS (Domain Name System).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;lookup-process&#34;&gt;Lookup Process&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In order for you to access a resource using a name, you need to now know the location of the system that contains the information (also known as &amp;lsquo;records&amp;rsquo;) for the resource you&amp;rsquo;re interested in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The idea being is that if you knew which DNS held a record containing information about the resource you wanted, you could &amp;lsquo;query&amp;rsquo; the DNS and say&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;ldquo;hey, what&amp;rsquo;s the ip for resource X?&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;the DNS would then respond with the information you needed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is what&amp;rsquo;s known as the &amp;lsquo;lookup process&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The lookup process is where your machine communicates across different networks until it finds one that knows the ip address of the resource you&amp;rsquo;re looking for. Now there are a few different parts to this lookup process:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Resolver&lt;/li&gt;&#xA;&lt;li&gt;Root Name Server(s)&lt;/li&gt;&#xA;&lt;li&gt;TLD Name Server(s)&lt;/li&gt;&#xA;&lt;li&gt;SLD Name Server(s)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;resolver&#34;&gt;Resolver&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &amp;lsquo;resolver&amp;rsquo; knows the location of the &amp;lsquo;root name server(s)&amp;rsquo;. When you make a request for a DNS resource, then the resolver is what you communicate with first. The resolver is typically either assigned via DHCP (client-side) or via &lt;code&gt;/etc/resolv.conf&lt;/code&gt; (server-side).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The resolver will have a &amp;lsquo;root hints&amp;rsquo; file with a hardcoded list of root name servers (there are thirteen root servers †). The resolver takes the DNS resource request and queries all the root name servers at once. Whichever root name server responds first, the resolver will keep a note of it as being the quickest (so for future requests it&amp;rsquo;ll favour that server over the other root name servers).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Resolvers also include additional logic for invalidating the favoured root name server, but that&amp;rsquo;s outside the scope of this article.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† there are only thirteen root server clusters, because that&amp;rsquo;s all that can fit inside a single UDP packet. Historically, DNS has operated through UDP packets, meaning the response to a request can never be more than 512 bytes.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now depending on what your query is, the resolver&amp;rsquo;s job isn&amp;rsquo;t necessarily finished. For some queries (such as &lt;code&gt;www.example.com&lt;/code&gt;) the resolver doesn&amp;rsquo;t just send a request to one level of name servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The resolve first makes a request to the root name servers, waits for a response and then sends &lt;em&gt;another&lt;/em&gt; query; this time the query is sent to a &amp;lsquo;sub level&amp;rsquo; name server known as a TLD name server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The TLD name server also returns a referral, this time to a SLD name server which the resolver will query. The SLD should now be able to identify the requested DNS resource.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;root-name-server-s&#34;&gt;Root Name Server(s)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are multiple root name servers and each one knows the location of a sub level name server capable of handling the requested DNS resource (or at least knowing the next level of name servers to delegate the request onto).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Effectively the root name servers parse the requested resource and identify which &amp;lsquo;TLD&amp;rsquo; name server the resolver should query. Once the root name server has identified the sub level name server, it returns that information to the resolver.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;tld-name-server-s&#34;&gt;TLD Name Server(s)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are multiple TLD name servers and each one knows the location of sub level name servers capable of handling the requested DNS resource and identifying its underlying ip address. The TLD name servers parse the requested resource and identify which &amp;lsquo;SLD&amp;rsquo; name server the resolver should query.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once the TLD name server has identified the SLD name server, it returns that information to the resolver.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;TLD name servers are split into two: gTLD (.com, .org, .net etc) and ccTLD (.us, .uk etc)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;sld-name-server-s&#34;&gt;SLD Name Server(s)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;SLD name servers are known by a few different names:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;User DNS name server&lt;/li&gt;&#xA;&lt;li&gt;Authoritative name server&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The latter (authoritative) being the most well known, because these name servers are the final step to hopefully discovering the identity of the requested DNS resource and this DNS server will be responsible for the DNS settings applied to the resource.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you may find some people use the term &amp;lsquo;authoritative&amp;rsquo; quite liberally, because in essence even a TLD name server can be considered authoritative in respect to the TLDs it manages (depends on your perspective)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;tree-hierarchy&#34;&gt;Tree Hierarchy&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It can be useful to try and visualise the hierarchy of this lookup process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code snippet shows a potential lookup flowing from an initial request to a &amp;lsquo;root&amp;rsquo; name server, into a &amp;lsquo;TLD&amp;rsquo; name server (I show both sub categories: gTLD and ccTLD just to be clearer); another request is then made to a specific gTLD (&lt;code&gt;.com&lt;/code&gt; in this case) and from there the next step is for the resolver to query the SLD (in this example we&amp;rsquo;re looking for the resource &lt;code&gt;www.example.com&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;         . (root)&#xA;        / \&#xA;       /   \&#xA;(gTLD).     .(ccTLD)&#xA;      \&#xA;       \&#xA;        .(com)&#xA;         \&#xA;          \&#xA;           .(example.com)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The requests that would have been made to fulfil the above flow diagram would have looked something like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Resolver makes multiple requests for &lt;code&gt;www.example.com&lt;/code&gt; to its list of root name servers&lt;/li&gt;&#xA;&lt;li&gt;One of the root name servers would have responded first to say &amp;ldquo;go talk to the .com gTLD&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;The resolver then sends the same &lt;code&gt;www.example.com&lt;/code&gt; query to the .com gTLD&lt;/li&gt;&#xA;&lt;li&gt;The gTLD responds to say &amp;ldquo;go talk to the &lt;code&gt;example.com&lt;/code&gt; authoritative name server&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;The resolver then sends the same &lt;code&gt;www.example.com&lt;/code&gt; query to the relevant authoritative name server&lt;/li&gt;&#xA;&lt;li&gt;The authoritative name server has the record the resolver is looking for and sends back its details&lt;/li&gt;&#xA;&lt;li&gt;The resolver can now provide those details back to the application who originated the request&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;so far we&amp;rsquo;ve spoken about name servers that run DNS software. There are many DNS software programs available (some paid, some free), but the most popular is &lt;a href=&#34;https://www.isc.org/downloads/bind/&#34; target=&#34;_blank&#34;&gt;BIND&lt;/a&gt;. We&amp;rsquo;ll see references to it throughout this article&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;dns-structure&#34;&gt;DNS Structure&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each period in a &amp;lsquo;domain&amp;rsquo; is actually a &amp;lsquo;level&amp;rsquo;. Hence extensions such as &lt;code&gt;.com&lt;/code&gt; or &lt;code&gt;.us&lt;/code&gt; are considered a TLD (top-level domain). This also explains why an SLD is named so: because it sits at a &amp;lsquo;secondary&amp;rsquo; level (it sits &amp;lsquo;below&amp;rsquo; the TLD).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The syntax structure of a domain resembles the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;protocol&amp;gt;&amp;lt;hostname&amp;gt;.&amp;lt;sld&amp;gt;.&amp;lt;tld&amp;gt;.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would materialise into something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;http://www.example.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Where&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;http://&lt;/code&gt; is the protocol&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;www&lt;/code&gt; is the hostname&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sld&lt;/code&gt; is &amp;lsquo;example&amp;rsquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;tld&lt;/code&gt; is &amp;lsquo;com&amp;rsquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;things get a little more complicated with ccTLDs&lt;br&gt;&#xA;As country codes can have a &lt;em&gt;third&lt;/em&gt; level (e.g. &lt;code&gt;example.co.uk&lt;/code&gt;)&lt;br&gt;&#xA;&lt;code&gt;uk&lt;/code&gt; (TLD), &lt;code&gt;co&lt;/code&gt; (SLD), &lt;code&gt;example&lt;/code&gt; (3LD)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Typically the combination of &lt;code&gt;&amp;lt;sld&amp;gt;&amp;lt;tld&amp;gt;&lt;/code&gt; is referred to as the &amp;lsquo;domain name&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;authority-zones&#34;&gt;Authority Zones&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now that we understand that a domain is made up of &amp;lsquo;levels&amp;rsquo;, the concept of &amp;lsquo;zones&amp;rsquo; should be easier to comprehend. A level is equivalent to a zone, but when using the term &amp;lsquo;zone&amp;rsquo; we&amp;rsquo;re being explicit in what &lt;em&gt;context&lt;/em&gt; we&amp;rsquo;re talking about. Effectively each zone is responsible (i.e. an authority) for its own resource records (RR).&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h3 id=&#34;zonefile&#34;&gt;Zonefile&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A resource record (RR) is simply a line in a text file. This text file defines what records have been created for the level/zone. Each authoritative name server (zone) has its own zonefile because it needs to be able to respond to requests (queries) for records it may have.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example of what a zonefile might look like for the domain &lt;code&gt;example.com&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$TTL    86400 ; 24 hours could have been written as 24h or 1d&#xA;$ORIGIN example.com.&#xA;@  1D  IN  SOA ns1.example.com. hostmaster.example.com. (&#xA;            2002022401 ; serial&#xA;            3H ; refresh&#xA;            15 ; retry&#xA;            1w ; expire&#xA;            3h ; minimum&#xA;           )&#xA;       IN  NS     ns1.example.com. ; in the domain&#xA;       IN  NS     ns2.smokeyjoe.com. ; external to domain&#xA;       IN  MX  10 mail.another.com. ; external mail provider&#xA;; server host definitions&#xA;ns1    IN  A      192.168.0.1  ;name server definition     &#xA;www    IN  A      192.168.0.2  ;web server definition&#xA;ftp    IN  CNAME  www.example.com.  ;ftp server definition&#xA;; non server domain hosts&#xA;bill   IN  A      192.168.0.3&#xA;fred   IN  A      192.168.0.4 &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The zonefile is effectively the mapping between a domain name and its associated ip address (as you&amp;rsquo;ll see later on, the use of tools such as &lt;code&gt;dig&lt;/code&gt; return us similar output).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above example zonefile we can see that we have a few records defined, such as an &amp;lsquo;A&amp;rsquo; record (e.g. &lt;code&gt;ns1&lt;/code&gt;, &lt;code&gt;www&lt;/code&gt;, &lt;code&gt;bill&lt;/code&gt; and &lt;code&gt;fred&lt;/code&gt;) and a &amp;lsquo;CNAME&amp;rsquo; record (&lt;code&gt;ftp&lt;/code&gt;), as well as a couple of &amp;lsquo;NS&amp;rsquo; records and a &amp;lsquo;MX&amp;rsquo; record. We&amp;rsquo;ll take a look at what these records really represent later on in this article.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The format for these records is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;name ttl class rr ...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;where &lt;code&gt;...&lt;/code&gt; represents specific arguments for the &lt;em&gt;type&lt;/em&gt; of RR being created&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The reason I mention this syntax structure is because there are some nuances regarding this zonefile that tie into the syntax structure but might not be immediately clear:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Anything starting with a &lt;code&gt;$&lt;/code&gt; is referred to as a &amp;lsquo;directive&amp;rsquo; and affects processing of the zonefile (e.g. &lt;code&gt;$TTL&lt;/code&gt; defines the default ttl for the entire zone; this can be overridden by a ttl set within a RR).&lt;/li&gt;&#xA;&lt;li&gt;The SOA record needs to be the first record defined&lt;/li&gt;&#xA;&lt;li&gt;The SOA record replaces &lt;code&gt;@&lt;/code&gt; with the value assigned to &lt;code&gt;$ORIGIN&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;$ORIGIN&lt;/code&gt; directive is not mandatory. If not provided, then BIND (the DNS server software) will acquire a value from the configuration file &lt;code&gt;named.conf&lt;/code&gt; (but generally it&amp;rsquo;s more portable to provide one in your zonefile)&lt;/li&gt;&#xA;&lt;li&gt;The SOA could be made into a one liner, but uses parentheses to indicate &amp;lsquo;multi-line&amp;rsquo;&lt;/li&gt;&#xA;&lt;li&gt;Not all arguments are mandatory and so can be left blank, by way of a space or a tab (known as a &amp;lsquo;field separator&amp;rsquo;)&lt;/li&gt;&#xA;&lt;li&gt;Most RR&amp;rsquo;s utilise &lt;code&gt;IN&lt;/code&gt; as the &amp;lsquo;class&amp;rsquo; value (which stands for &amp;lsquo;Internet&amp;rsquo;). There are other values but they&amp;rsquo;re very rarely used †&lt;/li&gt;&#xA;&lt;li&gt;The &amp;lsquo;name&amp;rsquo; used for most of the RR&amp;rsquo;s in the above example aren&amp;rsquo;t considered &amp;ldquo;fully qualified domain names&amp;rdquo;. I discuss what this means below, but for now you should know that the rule is: if the name doesn&amp;rsquo;t end with a dot &lt;code&gt;.&lt;/code&gt; then the &lt;code&gt;$ORIGIN&lt;/code&gt; is appended to the name (see next section for more details)&lt;/li&gt;&#xA;&lt;li&gt;With RRs you can have the same ip assigned to multiple names (as the one host could potentially be serving up different services, such as a DNS as well as a web server)&lt;/li&gt;&#xA;&lt;li&gt;You can simplify the creation of multiple records of the same RR type by omitting their value (see above example zonefile). For example, if no value for &lt;code&gt;rr&lt;/code&gt; is found then it&amp;rsquo;ll use the value from the previous record&lt;/li&gt;&#xA;&lt;li&gt;You can provide very basic DNS &amp;lsquo;load balancing&amp;rsquo; by creating multiple A records and pointing them to different ips. BIND will handle requests by carrying out either a round-robin process or a random selection (depending on the &lt;a href=&#34;http://www.zytrax.com/books/dns/ch7/queries.html#rrset-order&#34; target=&#34;_blank&#34;&gt;rrset-order&lt;/a&gt; setting inside the configuration &lt;code&gt;named.conf&lt;/code&gt;; round-robin being the default)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† the fields date back to an era where there were multiple computer networks in competition with each other. IN (internet) was just one of many. Others at the time might have been &lt;code&gt;CH&lt;/code&gt; (CHAOSNET) or &lt;code&gt;HS&lt;/code&gt; (Hesiod, and in part is still used by MIT students to this day). You&amp;rsquo;ll find all available references in the official &lt;a href=&#34;https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2&#34; target=&#34;_blank&#34;&gt;DNS Parameters RFC&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;To put this into context, consider the &lt;a href=&#34;https://www.icann.org/&#34; target=&#34;_blank&#34;&gt;ICANN&lt;/a&gt; organisation, who are responsible for providing an accreditation system for domain &amp;lsquo;registrars&amp;rsquo;. A domain registrar is an organisation who has been authorised to sell SLDs for a chosen TLD.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Registrars are a special entity who have been given &amp;lsquo;authority&amp;rsquo; over a set of TLDs. They&amp;rsquo;re able to create records for their zone (which is the top level domain itself).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, &lt;a href=&#34;https://www.123-reg.co.uk/&#34; target=&#34;_blank&#34;&gt;123-Reg&lt;/a&gt; is a domain registrar authorised to sell SLDs for all types of TLDs (such as &lt;code&gt;.org&lt;/code&gt;, &lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt;, &lt;code&gt;.co.uk&lt;/code&gt; etc). 123-Reg is a registrar who has (in my case) sold me the SLD (and technically a third-level domain) &lt;code&gt;integralist.co&lt;/code&gt; for the ccTLD &lt;code&gt;.uk&lt;/code&gt; - which means I&amp;rsquo;m the authority for &lt;code&gt;integralist.co.uk&lt;/code&gt; and can create records/hosts/sub domains for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This registrar could also sell the SLD &lt;code&gt;example&lt;/code&gt; (which gives &lt;em&gt;you&lt;/em&gt; ownership and responsibility for &lt;code&gt;example.com&lt;/code&gt; and everything to the left of it; e.g. you could create &lt;code&gt;www.example.com&lt;/code&gt;). Or maybe this registrar sells you a SLD/3LD combination for something like &lt;code&gt;example.co&lt;/code&gt; (which gives you ownership and responsibility for &lt;code&gt;example.co.uk&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you purchase a SLD (e.g. you could purchase the SLD &lt;code&gt;example&lt;/code&gt; under the TLD &lt;code&gt;.com&lt;/code&gt;), you are the authority for that zone (the SLD). This means you are able to create resource records for that zone.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you had &lt;code&gt;example.com&lt;/code&gt;, then you could create an A record &lt;code&gt;www&lt;/code&gt; which points to a specific ip address, or maybe you create a &lt;code&gt;blog&lt;/code&gt; CNAME record which acts as an alias to another service such as GitHub pages (we&amp;rsquo;ll see this demonstrated later on when looking at the different types of records in more detail).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately you have control over your zone (&lt;code&gt;example&lt;/code&gt;), and everything to the left of it, until you reach a new zone that has been delegated to another entity.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;fully-qualified-domains&#34;&gt;Fully Qualified Domains&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We should be clear that a &amp;lsquo;record&amp;rsquo; isn&amp;rsquo;t just the hostname part (e.g. &lt;code&gt;www&lt;/code&gt;). The record looks more like &lt;code&gt;www.example.com.&lt;/code&gt; (notice the dot on the end which indicates the &amp;lsquo;root&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most registrars provide a bit of visual sugar in their applications which mean you can create a record for &lt;code&gt;www.example.com.&lt;/code&gt; but only require you to enter &lt;code&gt;www&lt;/code&gt;, as they will add the &amp;lsquo;origin&amp;rsquo; (e.g. &lt;code&gt;example.com.&lt;/code&gt;) onto the end of the &lt;code&gt;www&lt;/code&gt; automatically for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Don&amp;rsquo;t be confused and think the &amp;lsquo;record&amp;rsquo; is &lt;em&gt;just&lt;/em&gt; &lt;code&gt;www&lt;/code&gt;; it&amp;rsquo;s not. This is why they are typically referred to as a &amp;ldquo;fully qualified domain&amp;rdquo; (FQD).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The dot on the end of the FQD indicates the root, the starting point of the DNS lookup hierarchy.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;practical-example&#34;&gt;Practical example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s nice to be able to see a practical example of how authority zones work (and in this case it&amp;rsquo;ll help with understanding some later examples I&amp;rsquo;ll be showing to you).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have the domain &lt;code&gt;integralist.co.uk&lt;/code&gt;. It has a zone defined there, but it also has a separate zone defined by the host/sub domain &lt;code&gt;www&lt;/code&gt;. So &lt;code&gt;www.integralist.co.uk&lt;/code&gt; is controlled by another entity (in my case a GitHub related entity).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why when looking at the SOA record (we&amp;rsquo;ll explain what this is later, but in summary it stands for &amp;ldquo;Start of Authority&amp;rdquo;) for &lt;code&gt;integralist.co.uk&lt;/code&gt; we&amp;rsquo;ll see that (as of 2015) 123-Reg is the authoritative name server, whereas if you look at &lt;code&gt;www.integralist.co.uk&lt;/code&gt; you&amp;rsquo;ll see that (again, as of 2015) Fastly is the authoritative name server as the &lt;code&gt;www&lt;/code&gt; host is set-up as a CNAME that is an alias pointing to GitHub, which in turn is a domain handled by Fastly.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;name-servers&#34;&gt;Name Servers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve mentioned &amp;lsquo;name servers&amp;rsquo; a few times so far in this article and that&amp;rsquo;s because they&amp;rsquo;re a key component within the lookup process for a DNS resource. A &amp;lsquo;name server&amp;rsquo; is a server that runs DNS software and is capable of mapping an ip to an easier to read/remember identifier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why the resolver pings a set of root name servers, as it knows it&amp;rsquo;ll either get back the ip for the requested domain name, or it&amp;rsquo;ll be referred to some other name server that can provide that information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When handling the DNS for a specific zone within your domain, you&amp;rsquo;ll likely set a NS (NameServer) record to point to a DNS service which allows you to administer DNS services for the zone you are the owner of. These name servers are typically referred to as a &amp;ldquo;primary&amp;rdquo; and &amp;ldquo;secondary&amp;rdquo; name server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The primary/secondary name servers are effectively where the authoritative name server (the servers handling DNS responsibilities) is split into sub sections. You&amp;rsquo;ll have one &amp;lsquo;primary&amp;rsquo; name server that contains the &amp;lsquo;zonedata&amp;rsquo; file(s) - also known as a zonefile - and then the secondary name server(s) will reference that zonefile via a mechanism known as &lt;a href=&#34;https://en.wikipedia.org/wiki/BIND&#34; target=&#34;_blank&#34;&gt;BIND&lt;/a&gt; (which is one of the largest DNS software implementations available).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the way zonefiles are replicated is a much bigger discussion topic and falls outside the focus of this article, but in short there have been a few alternative mechanisms implemented since BIND; such as: rsync, git and even database replication&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;commands&#34;&gt;Commands&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I want to take a slight detour now and quickly discuss a set of shell commands that are useful in debugging and querying the DNS. After this section I&amp;rsquo;ll be explaining the various &lt;em&gt;types&lt;/em&gt; of records available, and I&amp;rsquo;ll be using the following commands to help me demonstrate the different record types.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for the time being, don&amp;rsquo;t worry too much if you don&amp;rsquo;t feel you have a good handle on these commands after reading this section as this is just a light(ish) introduction, whereby I&amp;rsquo;ll start to elaborate on their usage more in the subsequent sections.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;whois&#34;&gt;&lt;code&gt;whois&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Taking the description direct from the manual:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The whois utility looks up records in the databases maintained by several Network Information Centers (NICs).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So if you want a very top level and general view of a domain and who owns/manages it, then the &lt;code&gt;whois&lt;/code&gt; command is for you. Typically you&amp;rsquo;ll use it to see who has registered a domain and to see the state of the domain (when was it last updated? when is it expiring? which organisation handles the DNS services? etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see what sort of data we get back when querying the domain for my website:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;whois integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would provide the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Domain name:&#xA;    integralist.co.uk&#xA;&#xA;Registrant:&#xA;    Mark McDonnell&#xA;&#xA;Registrant type:&#xA;    UK Individual&#xA;&#xA;Registrant&#39;s address:&#xA;    The registrant is a non-trading individual who has opted to have their&#xA;    address omitted from the WHOIS service.&#xA;&#xA;Data validation:&#xA;    Nominet was able to match the registrant&#39;s name and &#xA;    address against a 3rd party data source on 10-Dec-2012&#xA;&#xA;Registrar:&#xA;    123-Reg Limited t/a 123-reg [Tag = 123-REG]&#xA;    URL: http://www.123-reg.co.uk&#xA;&#xA;Relevant dates:&#xA;    Registered on: 19-Jul-2009&#xA;    Expiry date:  19-Jul-2017&#xA;    Last updated:  12-Jul-2015&#xA;&#xA;Registration status:&#xA;    Registered until expiry date.&#xA;&#xA;Name servers:&#xA;    ns.123-reg.co.uk&#xA;    ns2.123-reg.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the output will differ depending on the TLD (Top Level Domain)&lt;br&gt;&#xA;as they are managed by different NICs (Network Information Centers)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now there can be problems when doing a simple &lt;code&gt;whois &amp;lt;domain&amp;gt;&lt;/code&gt; query. For example, the below output is the result of executing the command &lt;code&gt;whois google.com&lt;/code&gt;. You&amp;rsquo;ll notice that we get back multiple name servers responsible for a &lt;code&gt;google.com&lt;/code&gt; domain (and not always the official Google you&amp;rsquo;re expecting):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Whois Server Version 2.0&#xA;&#xA;Domain names in the .com and .net domains can now be registered&#xA;with many different competing registrars. Go to http://www.internic.net&#xA;for detailed information.&#xA;&#xA;Aborting search 50 records found .....&#xA;GOOGLE.COM.AFRICANBATS.ORG&#xA;GOOGLE.COM.ANGRYPIRATES.COM&#xA;GOOGLE.COM.AR&#xA;GOOGLE.COM.AU&#xA;GOOGLE.COM.BAISAD.COM&#xA;GOOGLE.COM.BEYONDWHOIS.COM&#xA;GOOGLE.COM.BR&#xA;GOOGLE.COM.CN&#xA;GOOGLE.COM.CO&#xA;GOOGLE.COM.DO&#xA;GOOGLE.COM.FORSALE&#xA;GOOGLE.COM.HACKED.BY.JAPTRON.ES&#xA;GOOGLE.COM.HANNAHJESSICA.COM&#xA;GOOGLE.COM.HAS.LESS.FREE.PORN.IN.ITS.SEARCH.ENGINE.THAN.SECZY.COM&#xA;GOOGLE.COM.HK&#xA;GOOGLE.COM.HOUDA.DO.YOU.WANT.TO.MARRY.ME.JEN.RE&#xA;GOOGLE.COM.IS.APPROVED.BY.NUMEA.COM&#xA;GOOGLE.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET&#xA;GOOGLE.COM.LASERPIPE.COM.DOMAINPENDINGDELETE.COM&#xA;GOOGLE.COM.LOLOLOLOLOL.SHTHEAD.COM&#xA;GOOGLE.COM.MX&#xA;GOOGLE.COM.MY&#xA;GOOGLE.COM.NS1.CHALESHGAR.COM&#xA;GOOGLE.COM.NS2.CHALESHGAR.COM&#xA;GOOGLE.COM.PE&#xA;GOOGLE.COM.PK&#xA;GOOGLE.COM.SA&#xA;GOOGLE.COM.SHQIPERIA.COM&#xA;GOOGLE.COM.SOUTHBEACHNEEDLEARTISTRY.COM&#xA;GOOGLE.COM.SPAMMING.IS.UNETHICAL.PLEASE.STOP.THEM.HUAXUEERBAN.COM&#xA;GOOGLE.COM.SPROSIUYANDEKSA.RU&#xA;GOOGLE.COM.SUCKS.FIND.CRACKZ.WITH.SEARCH.GULLI.COM&#xA;GOOGLE.COM.TESTZZZZ.3000-RI.COM&#xA;GOOGLE.COM.TR&#xA;GOOGLE.COM.TW&#xA;GOOGLE.COM.UA&#xA;GOOGLE.COM.UK&#xA;GOOGLE.COM.UY&#xA;GOOGLE.COM.VABDAYOFF.COM&#xA;GOOGLE.COM.VN&#xA;GOOGLE.COM.WORDT.DOOR.VEEL.WHTERS.GEBRUIKT.SERVERTJE.NET&#xA;GOOGLE.COM.YUCEHOCA.COM&#xA;GOOGLE.COM.YUCEKIRBAC.COM&#xA;GOOGLE.COM.ZNAET.PRODOMEN.COM&#xA;GOOGLE.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM&#xA;GOOGLE.COM.ZZZZZZZZZZZZZ.GET.ONE.MILLION.DOLLARS.AT.WWW.UNIMUNDI.COM&#xA;GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZ.LOLLERSKATES.RENDRAG.NET&#xA;GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZZZZZZZ.HAVENDATA.COM&#xA;GOOGLE.COMICTOWEL.COM&#xA;GOOGLE.COM&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Only the last item in that list is the genuine Google domain we wanted to query (&lt;code&gt;GOOGLE.COM&lt;/code&gt;). So how do we query that specific domain and not get back all these other variants? To do that we need to find out the &amp;lsquo;whois server&amp;rsquo; for that domain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To find out the &amp;lsquo;whois server&amp;rsquo; (that is, the server which holds the &amp;lsquo;whois record&amp;rsquo;) we need to use the &lt;code&gt;=&lt;/code&gt; sign within our command, like so: &lt;code&gt;whois &#39;=google.com&#39;&lt;/code&gt; and from there you can discover the whois server and then we can use that information to help us query the server more directly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following output is from executing &lt;code&gt;whois &#39;=google.com&#39;&lt;/code&gt; and again is shortened for brevity (as there are quite a few results that come through), but this time we&amp;rsquo;re getting the &lt;code&gt;Whois Server&lt;/code&gt; information passed through. Notice out of the three records returned that only the last one is a genuine Google domain:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Server Name: GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZZZZZZZ.HAVENDATA.COM&#xA;IP Address: 162.251.82.121&#xA;Registrar: PDR LTD. D/B/A PUBLICDOMAINREGISTRY.COM&#xA;Whois Server: whois.PublicDomainRegistry.com&#xA;Referral URL: http://www.PublicDomainRegistry.com&#xA;&#xA;Server Name: GOOGLE.COMICTOWEL.COM&#xA;IP Address: 216.239.32.21&#xA;Registrar: GODADDY.COM, LLC&#xA;Whois Server: whois.godaddy.com&#xA;Referral URL: http://registrar.godaddy.com&#xA;&#xA;Domain Name: GOOGLE.COM&#xA;Registrar: MARKMONITOR INC.&#xA;Sponsoring Registrar IANA ID: 292&#xA;Whois Server: whois.markmonitor.com&#xA;Referral URL: http://www.markmonitor.com&#xA;Name Server: NS1.GOOGLE.COM&#xA;Name Server: NS2.GOOGLE.COM&#xA;Name Server: NS3.GOOGLE.COM&#xA;Name Server: NS4.GOOGLE.COM&#xA;Status: clientDeleteProhibited http://www.icann.org/epp#clientDeleteProhibited&#xA;Status: clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited&#xA;Status: clientUpdateProhibited http://www.icann.org/epp#clientUpdateProhibited&#xA;Status: serverDeleteProhibited http://www.icann.org/epp#serverDeleteProhibited&#xA;Status: serverTransferProhibited http://www.icann.org/epp#serverTransferProhibited&#xA;Status: serverUpdateProhibited http://www.icann.org/epp#serverUpdateProhibited&#xA;Updated Date: 20-jul-2011&#xA;Creation Date: 15-sep-1997&#xA;Expiration Date: 14-sep-2020&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the use of = in the &lt;code&gt;whois&lt;/code&gt; command doesn&amp;rsquo;t work with .uk TLD&amp;rsquo;s&lt;br&gt;&#xA;You&amp;rsquo;ll see an error about a strict no &lt;code&gt;=&lt;/code&gt; character allowed&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once you find the domain you&amp;rsquo;re after (in this case we want the real &lt;code&gt;google.com&lt;/code&gt;), you can filter out the &lt;code&gt;Whois Server&lt;/code&gt; line and use that to query the domain directly via the whois server responsible for the actual &lt;code&gt;google.com&lt;/code&gt; domain (this is done by adding the &lt;code&gt;-h&lt;/code&gt; flag to the &lt;code&gt;whois&lt;/code&gt; command):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;whois -h whois.markmonitor.com google.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Doing this we can now see the actual output we want:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Domain Name: google.com&#xA;Registry Domain ID: 2138514_DOMAIN_COM-VRSN&#xA;Registrar WHOIS Server: whois.markmonitor.com&#xA;Registrar URL: http://www.markmonitor.com&#xA;Updated Date: 2015-06-12T10:38:52-0700&#xA;Creation Date: 1997-09-15T00:00:00-0700&#xA;Registrar Registration Expiration Date: 2020-09-13T21:00:00-0700&#xA;Registrar: MarkMonitor, Inc.&#xA;Registrar IANA ID: 292&#xA;Registrar Abuse Contact Email: abusecomplaints@markmonitor.com&#xA;Registrar Abuse Contact Phone: +1.2083895740&#xA;Domain Status: clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)&#xA;Domain Status: clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)&#xA;Domain Status: clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)&#xA;Registry Registrant ID:&#xA;Registrant Name: Dns Admin&#xA;Registrant Organization: Google Inc.&#xA;Registrant Street: Please contact contact-admin@google.com, 1600 Amphitheatre Parkway&#xA;Registrant City: Mountain View&#xA;Registrant State/Province: CA&#xA;Registrant Postal Code: 94043&#xA;Registrant Country: US&#xA;Registrant Phone: +1.6502530000&#xA;Registrant Phone Ext:&#xA;Registrant Fax: +1.6506188571&#xA;Registrant Fax Ext:&#xA;Registrant Email: dns-admin@google.com&#xA;Registry Admin ID:&#xA;Admin Name: DNS Admin&#xA;Admin Organization: Google Inc.&#xA;Admin Street: 1600 Amphitheatre Parkway&#xA;Admin City: Mountain View&#xA;Admin State/Province: CA&#xA;Admin Postal Code: 94043&#xA;Admin Country: US&#xA;Admin Phone: +1.6506234000&#xA;Admin Phone Ext:&#xA;Admin Fax: +1.6506188571&#xA;Admin Fax Ext:&#xA;Admin Email: dns-admin@google.com&#xA;Registry Tech ID:&#xA;Tech Name: DNS Admin&#xA;Tech Organization: Google Inc.&#xA;Tech Street: 2400 E. Bayshore Pkwy&#xA;Tech City: Mountain View&#xA;Tech State/Province: CA&#xA;Tech Postal Code: 94043&#xA;Tech Country: US&#xA;Tech Phone: +1.6503300100&#xA;Tech Phone Ext:&#xA;Tech Fax: +1.6506181499&#xA;Tech Fax Ext:&#xA;Tech Email: dns-admin@google.com&#xA;Name Server: ns4.google.com&#xA;Name Server: ns2.google.com&#xA;Name Server: ns3.google.com&#xA;Name Server: ns1.google.com&#xA;DNSSEC: unsigned&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The structure of this variation of the &lt;code&gt;whois&lt;/code&gt; command is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;whois -h &amp;lt;whois_server&amp;gt; &amp;lt;domain&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;dig&#34;&gt;&lt;code&gt;dig&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Taking the description direct from the manual:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So &lt;code&gt;dig&lt;/code&gt; it turns out is, in a practical sense, a great DNS debugging tool. Let&amp;rsquo;s take a look at a quick example where we want to find out some DNS related information for the domain &lt;code&gt;integralist.co.uk&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Executing this command will give us back the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.8.3-P1 &amp;lt;&amp;lt;&amp;gt;&amp;gt; integralist.co.uk&#xA;;; global options: +cmd&#xA;;; Got answer:&#xA;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 5590&#xA;;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2&#xA;&#xA;;; QUESTION SECTION:&#xA;;integralist.co.uk.   IN  A&#xA;&#xA;;; ANSWER SECTION:&#xA;integralist.co.uk.  14400 IN  A 192.30.252.153&#xA;&#xA;;; AUTHORITY SECTION:&#xA;integralist.co.uk.  151529  IN  NS  ns2.123-reg.co.uk.&#xA;integralist.co.uk.  151529  IN  NS  ns.123-reg.co.uk.&#xA;&#xA;;; ADDITIONAL SECTION:&#xA;ns.123-reg.co.uk. 7 IN  A 212.67.202.2&#xA;ns2.123-reg.co.uk.  7 IN  A 92.51.159.40&#xA;&#xA;;; Query time: 94 msec&#xA;;; SERVER: 192.168.1.1#53(192.168.1.1)&#xA;;; WHEN: Sun Sep 27 15:32:02 2015&#xA;;; MSG SIZE  rcvd: 126&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This was a standard &lt;code&gt;dig&lt;/code&gt; command and so you&amp;rsquo;ll notice that the response has been split up into sections:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;HEADER&lt;/code&gt;: displays which options and flags have been enabled when executing the command (we&amp;rsquo;ll look at both options and flags in more detail later)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;QUESTION&lt;/code&gt;: displays which record you requested for the specified domain&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ANSWER&lt;/code&gt;: displays ttl (time to live) followed by record/ip for the specified domain&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;AUTHORITY&lt;/code&gt;: displays the authoritative name servers (i.e. the service handling DNS responsibilities)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ADDITIONAL&lt;/code&gt;: displays all the authoritative name servers available for querying (inc. their remaining ttl)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;STATS&lt;/code&gt;: displays basic stats such as query time, server ip, date of query, message size&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You can also specify a specific record type you want to query, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig ns integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which gives us back the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.8.3-P1 &amp;lt;&amp;lt;&amp;gt;&amp;gt; ns integralist.co.uk&#xA;;; global options: +cmd&#xA;;; Got answer:&#xA;;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 57285&#xA;;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2&#xA;&#xA;;; QUESTION SECTION:&#xA;;integralist.co.uk.        IN    NS&#xA;&#xA;;; ANSWER SECTION:&#xA;integralist.co.uk.    2671    IN    NS    ns.hosteurope.com.&#xA;integralist.co.uk.    2671    IN    NS    ns2.hosteurope.com.&#xA;&#xA;;; ADDITIONAL SECTION:&#xA;ns.hosteurope.com.    284    IN    A    212.67.202.2&#xA;ns2.hosteurope.com.    48488    IN    A    92.51.159.40&#xA;&#xA;;; Query time: 36 msec&#xA;;; SERVER: 192.168.1.1#53(192.168.1.1)&#xA;;; WHEN: Sun Sep 27 22:15:11 2015&#xA;;; MSG SIZE  rcvd: 116&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;flags&#34;&gt;Flags&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;In the response for a &lt;code&gt;dig&lt;/code&gt; command, under the header area, you&amp;rsquo;ll notice specific flags being set. These flags determine how the dig command should handle certain situations. The following flags are what you&amp;rsquo;ll likely see the most:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;QR (Query Response)&lt;/li&gt;&#xA;&lt;li&gt;RD (Recursion Desired)&lt;/li&gt;&#xA;&lt;li&gt;RA (Recursion Available)&lt;/li&gt;&#xA;&lt;li&gt;TC (TrunCated)&lt;/li&gt;&#xA;&lt;li&gt;AA (Authoritative Answer)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;When you execute a &lt;code&gt;dig&lt;/code&gt; command you&amp;rsquo;ll pretty much always see QR in the response (e.g. &lt;code&gt;flags: qr&lt;/code&gt;) because it indicates what you&amp;rsquo;re looking at is in fact the response.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The RD (&amp;ldquo;Recursion Desired&amp;rdquo;) flag (e.g. &lt;code&gt;flags: qr rd ra&lt;/code&gt;) means the query will keep referring queries until it finds an answer from an authoritative name server. The RD flag is set by default but can be disabled with the &lt;code&gt;+norecurse&lt;/code&gt; option. The reason for disabling this flag would be to help you identify if a RR (resource record) exists in a cache.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the RA flag (&amp;ldquo;Recursion Available&amp;rdquo;) in the response means the server is willing to allow recursion&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So if you wanted to see if one of the authoritative name servers for &lt;code&gt;integralist.co.uk&lt;/code&gt; had its &lt;code&gt;www&lt;/code&gt; CNAME record cached, then you would execute the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig @ns.123-reg.co.uk www.integralist.co.uk +norecurse&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If the response doesn&amp;rsquo;t have an &lt;code&gt;ANSWER&lt;/code&gt; section, then you know it has been cached.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The TC flag (&amp;ldquo;TrunCated&amp;rdquo;) is used for when a UDP response is larger than 512 bytes. The response will set TC to 1 and so the client/resolver will need to try again, this time using TCP instead of UDP so it can retrieve the full response.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;enabling TC can be used as a DDoS mitigation technique - where the layers in front of your name servers will purposely set TC on - so if an attacker tries using UDP when attacking your DNS, then their request will immediately fail and they&amp;rsquo;ll be required to try again using TCP (as TCP connections is easier to filter); but it&amp;rsquo;s unlikely that an automated DDoS attack will retry a failed attempt&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll normally see the AA flag in the response (e.g. &lt;code&gt;flags: qr aa&lt;/code&gt;) when you query an authoritative name server directly (like we did above when checking to see if the &lt;code&gt;www&lt;/code&gt; CNAME for &lt;code&gt;integralist.co.uk&lt;/code&gt; was stored in a cache).&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;option-nostats&#34;&gt;option: nostats&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Enabling &amp;lsquo;no stats&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig www.integralist.co.uk +nostats&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The response will be missing the following section:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;;; Query time: 7 msec&#xA;;; SERVER: 192.168.253.250#53(192.168.253.250)&#xA;;; WHEN: Wed Sep 23 08:52:18 2015&#xA;;; MSG SIZE  rcvd: 273&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;personally I think this is safe to enable for the majority of use cases (stats are just visual noise I can do without)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;option-nocomments&#34;&gt;option: nocomments&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Enabling &amp;lsquo;no comments&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig www.integralist.co.uk +nocomments&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The response will look something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.8.3-P1 &amp;lt;&amp;lt;&amp;gt;&amp;gt; www.integralist.co.uk +nocomments&#xA;;; global options: +cmd&#xA;;www.integralist.co.uk.         IN      A&#xA;www.integralist.co.uk.  13920   IN      CNAME   integralist.github.com.&#xA;integralist.github.com. 17      IN      CNAME   github.map.fastly.net.&#xA;github.map.fastly.net.  2       IN      A       185.31.18.133&#xA;;; Query time: 0 msec&#xA;;; SERVER: 192.168.253.250#53(192.168.253.250)&#xA;;; WHEN: Wed Sep 23 08:54:50 2015&#xA;;; MSG SIZE  rcvd: 126&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice that all the major &amp;lsquo;sections&amp;rsquo; have been removed, such as &lt;code&gt;;; Got answer:&lt;/code&gt;, &lt;code&gt;;; QUESTION SECTION:&lt;/code&gt; and &lt;code&gt;;; ANSWER SECTION:&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;option-trace&#34;&gt;option: trace&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Trace is disabled by default so this is the first option we&amp;rsquo;ve looked at that &lt;em&gt;actually&lt;/em&gt; needs &amp;lsquo;enabling&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig www.integralist.co.uk +trace&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What this will do is display the full delegation path and show all referrals:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.8.3-P1 &amp;lt;&amp;lt;&amp;gt;&amp;gt; www.integralist.co.uk +trace&#xA;;; global options: +cmd&#xA;.            489215    IN    NS    e.root-servers.net.&#xA;.            489215    IN    NS    k.root-servers.net.&#xA;.            489215    IN    NS    m.root-servers.net.&#xA;.            489215    IN    NS    h.root-servers.net.&#xA;.            489215    IN    NS    d.root-servers.net.&#xA;.            489215    IN    NS    j.root-servers.net.&#xA;.            489215    IN    NS    f.root-servers.net.&#xA;.            489215    IN    NS    c.root-servers.net.&#xA;.            489215    IN    NS    g.root-servers.net.&#xA;.            489215    IN    NS    l.root-servers.net.&#xA;.            489215    IN    NS    b.root-servers.net.&#xA;.            489215    IN    NS    i.root-servers.net.&#xA;.            489215    IN    NS    a.root-servers.net.&#xA;;; Received 496 bytes from 192.168.1.1#53(192.168.1.1) in 85 ms&#xA;&#xA;uk.            172800    IN    NS    nsa.nic.uk.&#xA;uk.            172800    IN    NS    nsb.nic.uk.&#xA;uk.            172800    IN    NS    nsc.nic.uk.&#xA;uk.            172800    IN    NS    nsd.nic.uk.&#xA;uk.            172800    IN    NS    dns1.nic.uk.&#xA;uk.            172800    IN    NS    dns2.nic.uk.&#xA;uk.            172800    IN    NS    dns3.nic.uk.&#xA;uk.            172800    IN    NS    dns4.nic.uk.&#xA;;; Received 459 bytes from 128.63.2.53#53(128.63.2.53) in 96 ms&#xA;&#xA;integralist.co.uk.    172800    IN    NS    ns.123-reg.co.uk.&#xA;integralist.co.uk.    172800    IN    NS    ns2.123-reg.co.uk.&#xA;;; Received 82 bytes from 103.49.80.1#53(103.49.80.1) in 75 ms&#xA;&#xA;www.integralist.co.uk.    14400    IN    CNAME    integralist.github.com.&#xA;;; Received 75 bytes from 212.67.202.2#53(212.67.202.2) in 21 ms&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;other-options&#34;&gt;Other options&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;For a full list of options that you can play around with, I suggest reviewing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;man dig&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;host&#34;&gt;&lt;code&gt;host&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Taking the description direct from the manual:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;host&lt;/code&gt; is a simple utility for performing DNS lookups&lt;br&gt;&#xA;It is normally used to convert names to IP addresses and vice versa&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So a much more basic version of &lt;code&gt;dig&lt;/code&gt; but in certain circumstances I could imagine it offering more semantic clarity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A simple example would be as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;host www.integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Running the above command would return to us the ip address for the specified domain. In this case it would return:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;www.integralist.co.uk is an alias for integralist.github.com.&#xA;integralist.github.com is an alias for github.map.fastly.net.&#xA;github.map.fastly.net has address 23.235.43.133&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice it displayed the full resolution path:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;CNAME alias to Github pages&lt;/li&gt;&#xA;&lt;li&gt;CNAME alias to Fastly&lt;/li&gt;&#xA;&lt;li&gt;ip address for Fastly&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now if you tried using the non-www version:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;host integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;d find you get a different response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;integralist.co.uk has address 192.30.252.153&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is because my domain uses a redirect to &lt;code&gt;www.integralist.co.uk&lt;/code&gt;, which is then a CNAME alias to GitHub. So if I carried out the reverse lookup using the ip address above:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;host 192.30.252.153&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I would subsequently get back the following response, which indicates that my website is actually hosted with &lt;a href=&#34;https://pages.github.com/&#34; target=&#34;_blank&#34;&gt;GitHub Pages&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;153.252.30.192.in-addr.arpa domain name pointer pages.github.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; can do the same with &lt;code&gt;dig -x &amp;lt;ip&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;nslookup&#34;&gt;&lt;code&gt;nslookup&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Taking the description direct from the manual:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;nslookup&lt;/code&gt; is a program to query Internet domain name servers&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;nslookup&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From here you&amp;rsquo;ll be prompted to specify a domain, so for example we could now type:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;gt; integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which would return the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Server:   192.168.1.1&#xA;Address:  192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;Name: integralist.co.uk&#xA;Address: 192.30.252.153&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If I was to now use &lt;code&gt;host&lt;/code&gt; to find the name this ip resolves to:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;host 192.30.252.153&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It would display:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;153.252.30.192.in-addr.arpa domain name pointer pages.github.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Cool, so again we end up at GitHub pages where my website is hosted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I was to use &lt;code&gt;nslookup&lt;/code&gt; on the &lt;code&gt;www&lt;/code&gt; variation of my website then I&amp;rsquo;d see a slightly different response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;gt; www.integralist.co.uk&#xA;&#xA;Server:        192.168.1.1&#xA;Address:    192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;www.integralist.co.uk    canonical name = integralist.github.com.&#xA;integralist.github.com    canonical name = github.map.fastly.net.&#xA;Name:    github.map.fastly.net&#xA;Address: 23.235.43.133&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can also use &lt;code&gt;nslookup&lt;/code&gt; to return specific record information. Imagine we want to see the SOA record for &lt;code&gt;integralist.co.uk&lt;/code&gt;. We can do this by typing &lt;code&gt;set querytype=soa&lt;/code&gt; followed by the domain, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;nslookup&#xA;&#xA;&amp;gt; set querytype=soa&#xA;&amp;gt; integralist.co.uk                        &#xA;&#xA;Server:        192.168.1.1&#xA;Address:    192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;integralist.co.uk&#xA;  origin = ns.hosteurope.com&#xA;  mail addr = hostmaster.integralist.co.uk&#xA;  serial = 2012022703&#xA;  refresh = 86400&#xA;  retry = 3600&#xA;  expire = 1209600&#xA;  minimum = 14400&#xA;&#xA;Authoritative answers can be found from:&#xA;integralist.co.uk    nameserver = ns.123-reg.co.uk.&#xA;integralist.co.uk    nameserver = ns2.123-reg.co.uk.&#xA;ns.123-reg.co.uk    internet address = 212.67.202.2&#xA;ns2.123-reg.co.uk    internet address = 92.51.159.40&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can also see this provides us with an authoritative answer. But as we already know, querying the &lt;code&gt;www&lt;/code&gt; host/sub domain will return us slightly different information:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Server:        192.168.1.1&#xA;Address:    192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;www.integralist.co.uk    canonical name = integralist.github.com.&#xA;integralist.github.com    canonical name = github.map.fastly.net.&#xA;&#xA;Authoritative answers can be found from:&#xA;fastly.net&#xA;  origin = ns1.p04.dynect.net&#xA;  mail addr = hostmaster.fastly.com&#xA;  serial = 2015092706&#xA;  refresh = 3600&#xA;  retry = 600&#xA;  expire = 604800&#xA;  minimum = 3600&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So if we decided to try this again but specify the record type as being a CNAME record:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;nslookup&#xA;&#xA;&amp;gt; set querytype=cname&#xA;&amp;gt; integralist.co.uk&#xA;&#xA;Server:        192.168.1.1&#xA;Address:    192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;*** Can&#39;t find integralist.co.uk: No answer&#xA;&#xA;Authoritative answers can be found from:&#xA;integralist.co.uk&#xA;  origin = ns.hosteurope.com&#xA;  mail addr = hostmaster.integralist.co.uk&#xA;  serial = 2012022703&#xA;  refresh = 86400&#xA;  retry = 3600&#xA;  expire = 1209600&#xA;  minimum = 14400&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We see we get back an error that says there is no answer for this type of query. But if I was to try again and now use the host/sub domain &lt;code&gt;www&lt;/code&gt; (which I know to be a CNAME) then we get the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Server:        192.168.1.1&#xA;Address:    192.168.1.1#53&#xA;&#xA;Non-authoritative answer:&#xA;www.integralist.co.uk    canonical name = integralist.github.com.&#xA;&#xA;Authoritative answers can be found from:&#xA;integralist.co.uk    nameserver = ns.hosteurope.com.&#xA;integralist.co.uk    nameserver = ns2.hosteurope.com.&#xA;ns.hosteurope.com    internet address = 212.67.202.2&#xA;ns2.hosteurope.com    internet address = 92.51.159.40&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now we see that &lt;code&gt;www.integralist.co.uk&lt;/code&gt; is a CNAME (Canonical Name) to &lt;code&gt;integralist.github.com&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to exit &lt;code&gt;nslookup&lt;/code&gt; press &lt;code&gt;&amp;lt;Ctrl-c&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;record-types&#34;&gt;Record Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many different RR (Resource Record) types availble within DNS, the following are the most popular:&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;ns&#34;&gt;NS&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The NS record should be pointed to the entity responsible for handling DNS duties for your domain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You must have at least two name server records for the sake of resiliency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The sequence/ordering of listed name servers has nothing to do with priority (unlike with MX records, see below for more details). For example, the following process &lt;strong&gt;DOESN&amp;rsquo;T&lt;/strong&gt; happen: &amp;ldquo;query the A name server first and if no response &lt;em&gt;then&lt;/em&gt; query the B name server&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Multiple NS records simply means that there are multiple name servers available to query for the records required by the client application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The NS record indicates the authoritative name servers for the current origin. But remember that different parts of an overall domain can be controlled by different entities (i.e. different Zone/SOA).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in seeing which root servers are responsible for knowing about a particular TLD, then again we can use &lt;code&gt;dig&lt;/code&gt; to find this information. For example, to see the ccTLD name servers for &lt;code&gt;.co.uk&lt;/code&gt; execute the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig +short -t ns co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we use the &lt;code&gt;+short&lt;/code&gt; flag provided by &lt;code&gt;dig&lt;/code&gt;&lt;br&gt;&#xA;This enables us to reduce the visual noise&lt;br&gt;&#xA;Another trick is to use &lt;code&gt;+short +noshort&lt;/code&gt; together&lt;br&gt;&#xA;Which gives you reduced noise + additional info&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This will return the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dnsd.nic.uk.&#xA;dns4.nic.uk.&#xA;nsb.nic.uk.&#xA;dns1.nic.uk.&#xA;dns2.nic.uk.&#xA;nsc.nic.uk.&#xA;nsa.nic.uk.&#xA;dns3.nic.uk.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in seeing the very root servers which your resolver will query for information about a particular domain then you can use the following variation of the &lt;code&gt;dig&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig +short -t ns .&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you&amp;rsquo;ll notice the dot on the end&lt;br&gt;&#xA;As we&amp;rsquo;ve mentioned previously,&lt;br&gt;&#xA;the dot represents the &amp;lsquo;root&amp;rsquo; of the DNS hierarchy&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Executing this command will return the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;a.root-servers.net.&#xA;b.root-servers.net.&#xA;c.root-servers.net.&#xA;d.root-servers.net.&#xA;e.root-servers.net.&#xA;f.root-servers.net.&#xA;g.root-servers.net.&#xA;h.root-servers.net.&#xA;i.root-servers.net.&#xA;j.root-servers.net.&#xA;k.root-servers.net.&#xA;l.root-servers.net.&#xA;m.root-servers.net.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;a&#34;&gt;A&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An A record should point to an ip address (i.e. it&amp;rsquo;s an &amp;ldquo;address record&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to provide redundancy, you can have multiple A records associated with a domain. For example, imagine your service is sitting behind a load balancer such as &lt;a href=&#34;https://aws.amazon.com/elasticloadbalancing/&#34; target=&#34;_blank&#34;&gt;AWS ELB&lt;/a&gt;. What you would likely do is create a CNAME (see below section for more details) that points to your load balancer&amp;rsquo;s own CNAME (it&amp;rsquo;s unlikely you&amp;rsquo;ll point your domain to a direct ip address when using a load balancer because if the load balancer changes then you&amp;rsquo;d need to update your DNS, which would result in potentially significant downtime) and then the load balancer would handle the responsibility of creating multiple A records that point to the actual ip addresses of your running servers.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;cname&#34;&gt;CNAME&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A CNAME record is one that points not to an ip address (like an A record does), but instead points to either a CNAME or A record.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see a real world example by &lt;code&gt;dig&lt;/code&gt;ing this website (specifically the &lt;code&gt;www&lt;/code&gt; host name):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig www.integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The information returned (see below), indicates that we have a CNAME (&lt;code&gt;www.integralist.co.uk.&lt;/code&gt;) that points to GitHub (&lt;code&gt;integralist.github.com.&lt;/code&gt;); and that in turn points to an A record (&lt;code&gt;github.map.fastly.net.&lt;/code&gt;), which itself points to the ip address of the server hosting the content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;;; ANSWER SECTION:&#xA;www.integralist.co.uk.  14266   IN      CNAME   integralist.github.com.&#xA;integralist.github.com. 2       IN      CNAME   github.map.fastly.net.&#xA;github.map.fastly.net.  17      IN      A       185.31.19.133&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-important&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;❗ IMPORTANT&lt;/p&gt;&lt;p&gt;A CNAME in DNS serves to map one name to another source of truth for &lt;strong&gt;ALL&lt;/strong&gt; DNS resource record types.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So if you have:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;service.example.com. IN CNAME other.service.example.net.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An A Record lookup for &lt;code&gt;service.example.com.&lt;/code&gt; will return the A record of &lt;code&gt;other.service.example.net.&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An MX Record lookup for &lt;code&gt;service.example.com.&lt;/code&gt; will return the MX record of &lt;code&gt;other.service.example.net.&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A TXT Record lookup for &lt;code&gt;service.example.com.&lt;/code&gt; will return the TXT record of &lt;code&gt;other.service.example.net.&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;mx&#34;&gt;MX&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I wont spend much time on MX records, but in short it stands for &amp;ldquo;Mail eXchange&amp;rdquo; and you can have multiple records for the purposes of redundancy. Each MX record has a &amp;lsquo;priority value&amp;rsquo; which indicates a relative value compared to the other MX records listed. What this means is that a lower value is considered a higher priority and so it&amp;rsquo;s used first when directing email.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I don&amp;rsquo;t have email set-up for my &lt;code&gt;integralist.co.uk&lt;/code&gt; domain so &lt;code&gt;dig mx integralist.co.uk&lt;/code&gt; wont help me demonstrate anything. Instead let&amp;rsquo;s look at the BBC:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig mx bbc.co.uk +short&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will return the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;20 cluster1a.eu.messagelabs.com.&#xA;10 cluster1.eu.messagelabs.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, the BBC appear to be using &lt;code&gt;http://messagelabs.com/&lt;/code&gt; as the entry point for managing their email systems.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;soa&#34;&gt;SOA&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Near the beginning of this article we discussed the concept of &amp;lsquo;zones&amp;rsquo; to indicate which entity had authority over the DNS for a specific section of a domain. An SOA record (which stands for &amp;ldquo;Start of Authority&amp;rdquo;) details specific information related to TTLs regarding the current zone.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for example, if I look at the SOA for &lt;code&gt;integralist.co.uk&lt;/code&gt; using the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig soa integralist.co.uk +short&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I would get back the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ns.hosteurope.com. hostmaster.integralist.co.uk. 2012022703 86400 3600 1209600 14400&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s break down this response into sections:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ns.hosteurope.com.&lt;/code&gt;: primary authoritative name server&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hostmaster.integralist.co.uk.&lt;/code&gt;: party responsible for your domain&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;2012022703&lt;/code&gt;: timestamp that is updated when the domain is updated&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;86400&lt;/code&gt;: zone refresh TTL (in seconds)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;3600&lt;/code&gt;: failed zone refresh retry (in seconds)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;1209600&lt;/code&gt;: zone authoritative ownership expiration (in seconds)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;14400&lt;/code&gt;: negative result TTL (how long resolver should consider a &amp;lsquo;negative result&amp;rsquo; for a subdomain to be a valid result before retrying a query to the host/subdomain&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Each &amp;lsquo;zone&amp;rsquo; (i.e. each name server/entity who has authority at a specific point of the domain) will provide their own SOA record. So if I were to look at the CNAME &lt;code&gt;www&lt;/code&gt; for &lt;code&gt;integralist.co.uk&lt;/code&gt;, then I would find that this points to a GitHub CNAME which points to a Fastly CNAME, and whose authoritative name servers are (as of 2015) &lt;code&gt;ns1.p04.dynect.net&lt;/code&gt;. This means a new &amp;lsquo;zone&amp;rsquo; is defined by Fastly and so they have authority to add host names to the left of the &lt;code&gt;www&lt;/code&gt; section of the overall domain:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig soa www.integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I would get back the following response:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;;; QUESTION SECTION:&#xA;;www.integralist.co.uk.        IN    SOA&#xA;&#xA;;; ANSWER SECTION:&#xA;www.integralist.co.uk.    14389    IN    CNAME    integralist.github.com.&#xA;integralist.github.com.    19    IN    CNAME    github.map.fastly.net.&#xA;&#xA;;; AUTHORITY SECTION:&#xA;fastly.net.        289    IN    SOA    ns1.p04.dynect.net. hostmaster.fastly.com. 201 3600 600 604800 3600&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;srv&#34;&gt;SRV&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The purpose of an SRV record is simply to provide information about services available via your domain. You&amp;rsquo;ll find services such as &lt;a href=&#34;http://blog.gopheracademy.com/skydns/&#34; target=&#34;_blank&#34;&gt;SkyDNS&lt;/a&gt; and &lt;a href=&#34;https://github.com/coreos/etcd&#34; target=&#34;_blank&#34;&gt;Etc&lt;/a&gt; use DNS and specifically SRV records as a way of handling distributed &amp;lsquo;service discovery&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is a very specific format to the records, which looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;_&amp;lt;name&amp;gt;._&amp;lt;protocol&amp;gt;.&amp;lt;domain&amp;gt;.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &amp;lsquo;name&amp;rsquo; should be a easy to identify name&lt;br&gt;&#xA;but otherwise there isn&amp;rsquo;t any other structure or restrictions I know of&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So if I wanted to indicate to some other service or application that I had a website available somewhere underneath the top level domain &lt;code&gt;integralist.co.uk&lt;/code&gt; then I would create the following SRV record:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;_website._tcp.integralist.co.uk.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You could then verify the SRV record was set-up by using &lt;code&gt;dig&lt;/code&gt; like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig _website._tcp.integralist.co.uk SRV +short +noshort&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This would respond with the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;_website._tcp.integralist.co.uk. 14400 IN SRV 11 1 80 www.integralist.co.uk.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I set this up using my DNS provider&amp;rsquo;s own GUI (so your own provider may have a different interface), but effectively the response indicates to a requester that I have a single service available at &lt;code&gt;www.integralist.co.uk&lt;/code&gt; which you can access via TCP on port &lt;code&gt;80&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The full details of which are broken down into sections, like so:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Hostname&lt;/code&gt;: &lt;code&gt;_website._tcp&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Type&lt;/code&gt;: &lt;code&gt;SRV&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Priority&lt;/code&gt;: &lt;code&gt;11&lt;/code&gt; (a lower number is a higher priority)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;TTL&lt;/code&gt;: &lt;code&gt;60&lt;/code&gt; (in seconds)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Destination&lt;/code&gt;: &lt;code&gt;1 80 www.integralist.co.uk.&lt;/code&gt; (&lt;code&gt;&amp;lt;weight&amp;gt; &amp;lt;port&amp;gt; &amp;lt;fully-qualified origin&amp;gt;&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;priority&lt;/code&gt; is useful for when you have multiple hosts configured for the same service, while the &lt;code&gt;weight&lt;/code&gt; is typically used for services that have the same &lt;code&gt;priority&lt;/code&gt; value&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;ptr&#34;&gt;PTR&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The PTR record is surprisingly complex in its implementation and yet fairly simple with regards to its purpose and set-up. In short you use the PTR to do a &lt;em&gt;reverse-mapping&lt;/em&gt;, which is the process of forwarding an ip to a hostname (the typical RR process is known as &lt;em&gt;forward-mapping&lt;/em&gt;, where by you forward a hostname onto an ip).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The purpose of a PTR record is traditionally for authentication/security reasons. Think of mail servers that try to prevent spam messages being sent from what looks like valid hosts. In this scenario the mail server will attempt to verify that the host/ip match both ways: forward and reverse. If they don&amp;rsquo;t match then the mail is rejected.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the past when I&amp;rsquo;ve had clients complain their emails are being rejected by their intended recipient, you&amp;rsquo;ll find they&amp;rsquo;re missing a PTR record in their DNS. The recipient&amp;rsquo;s email provider will nearly always request we add a PTR record to our client&amp;rsquo;s DNS&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I won&amp;rsquo;t go into the implementation details here, as I mentioned earlier it&amp;rsquo;s quite complex, but in essence there is another top level domain called &lt;code&gt;arpa&lt;/code&gt; with a sub level domain &lt;code&gt;in-addr&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This new domain works in a similar way to gTLD and ccTLDs in the sense that it has third level domains, but the difference is that the order is reversed from this point. So if your web server&amp;rsquo;s ip was &lt;code&gt;185.31.19.133&lt;/code&gt; then the third level domain would use &lt;code&gt;185&lt;/code&gt; as the name. These third level domains will also have their own zonefiles that describe the DNS at that level.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the zonefile you would see something like the following (notice the ip address we mentioned above has been reversed due to the standard DNS hierarchy structure):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ORIGIN 19.31.185.IN-ADDR.ARPA.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;convention states that although domains are case-insensitive, the &lt;code&gt;in-addr.arpa.&lt;/code&gt; should be capitalised&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;As far as the PTR record is concerned, you now take the last part of your ip and use that as the name of your PTR record. For example, if you had the ip &lt;code&gt;185.31.19.133&lt;/code&gt; then &lt;code&gt;133&lt;/code&gt; would be the name of the PTR record, while its value would be a fully qualified domain such as &lt;code&gt;www.example.com.&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;133      IN    PTR    www.example.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because we&amp;rsquo;ve defined an &lt;code&gt;$ORIGIN&lt;/code&gt; in our zonefile that is an arpa address we&amp;rsquo;d typically use fully qualified domain names for all other RRs (such as we have in the above PTR example)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This now means that the DNS can carry out a reverse-lookup, and for the ip &lt;code&gt;185.31.19.133&lt;/code&gt; it&amp;rsquo;ll locate the &lt;code&gt;133&lt;/code&gt; PTR record and see that is resolves to &lt;code&gt;www.example.com.&lt;/code&gt; which when doing a forward-mapping DNS request results in the ip &lt;code&gt;185.31.19.133&lt;/code&gt; thus providing reasonable authentication that the queries are related and not being spoofed.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;txt&#34;&gt;TXT&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The TXT record simply provides a description for the domain being queried. You must also wrap the description in double quotes (if you&amp;rsquo;re adding this record via a DNS provider then they might do this for you as you&amp;rsquo;ll likely be typing the value of this record into a HTML input field).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see a real-world example of this record using both &lt;code&gt;dig&lt;/code&gt; and &lt;code&gt;host&lt;/code&gt; commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig txt my-service-description.integralist.co.uk +short&#xA;host -t txt my-service-description.integralist.co.uk&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This query should return a response similar to the following (it&amp;rsquo;ll be slightly different for the &lt;code&gt;host&lt;/code&gt; command as it has no comparible flag to &lt;code&gt;dig&lt;/code&gt;&amp;rsquo;s &lt;code&gt;+short&lt;/code&gt; flag):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;integralist.co.uk is a tech blog&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if no TXT record is found then &lt;code&gt;dig&lt;/code&gt; will return nothing, whereas &lt;code&gt;host&lt;/code&gt; will return &lt;code&gt;integralist.co.uk has no TXT record&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;When I initially set-up the TXT record, it wasn&amp;rsquo;t available via my local DNS resolver and so in the following example I query one of the authoritative name servers as well as a Google server to see the new TXT record before it has propagated around the internet:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig txt my-service-description.integralist.co.uk @ns.123-reg.co.uk. +short&#xA;dig txt my-service-description.integralist.co.uk @8.8.8.8 +short&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;8.8.8.8&lt;/code&gt; is one of Google&amp;rsquo;s own DNS name servers and although not an authoritative name server for my domain, it was very fast at getting the new record&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;ttl-time-to-live&#34;&gt;TTL (Time to Live)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Every resource record (e.g. A, MX, CNAME etc) has a TTL set for it. When you make a request for a record, it will be cached for the length of time that the TTL is set. This is both good and a bad thing (as is usually the case with caching scenarios) as you need to find a good balance between a TTL that&amp;rsquo;s too high (meaning you lose the &amp;lsquo;freshness&amp;rsquo; for DNS updates) and a TTL that&amp;rsquo;s too low (and subsequently ends up affecting the performance of your server).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following example, which is a query for an MX record from the BBC:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig mx bbc.co.uk +short +noshort&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The response to this query is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;bbc.co.uk.        300    IN    MX    10 cluster1.eu.messagelabs.com.&#xA;bbc.co.uk.        300    IN    MX    20 cluster1a.eu.messagelabs.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can see the TTL for this record is 300 seconds (that&amp;rsquo;s 5 minutes). If you were to execute the same &lt;code&gt;dig&lt;/code&gt; command again, you would now notice the value for the TTL has dropped. Run it yet again and you&amp;rsquo;ll see the value drops even more. This is the TTL expiring second by second.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you make a change to your DNS and are wondering why it hasn&amp;rsquo;t taken effect, this might be because it&amp;rsquo;s cached and waiting to expire before the new changes are visible.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;local-caching&#34;&gt;Local Caching&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you want to bypass your local ISP caching of DNS requests, then you&amp;rsquo;ll need to query an authoritative name server directly to see if the change has indeed been made and is just waiting to take effect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following snippet demonstrates the command syntax structure using &lt;code&gt;dig&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;dig &amp;lt;domain&amp;gt; @&amp;lt;authoritative_nameserver&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If after executing the query the response is the one you expect, then it means the record has been updated in your DNS provider&amp;rsquo;s system but the changes still need to propagate.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920034148.do&#34; target=&#34;_blank&#34;&gt;Managing Mission-Critical Domains and DNS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.apress.com/9781590594940&#34; target=&#34;_blank&#34;&gt;Pro DNS and BIND&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://www.slashroot.in/what-dns-zone-file-complete-tutorial-zone-file-and-its-contents&#34; target=&#34;_blank&#34;&gt;What is a DNS ZONE file&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Although a fairly long article, this has really only barely scratched the surface of what&amp;rsquo;s possible with DNS. I&amp;rsquo;ll be improving the contents of this page over the next few weeks, as I learn more, so stayed tuned for updates. If there are any glaring issues or inaccurate details then do please let me know. Feedback is always welcome.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/dns-101/</guid>
      <link>https://www.integralist.co.uk/posts/dns-101/</link>
      <pubDate>Wed, 30 Sep 2015 00:00:00 +0000</pubDate>
      <title>DNS 101</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;UPDATE: for those short on time, read the following &lt;a href=&#34;#1&#34;&gt;Introduction&lt;/a&gt;, &lt;a href=&#34;#2&#34;&gt;What are keys and how do they work?&lt;/a&gt; and then skip over the sections &amp;ldquo;Understanding PKI&amp;rdquo; and &amp;ldquo;OpenSSL vs OpenSSH&amp;rdquo; as these just go into more depth on the technical aspect of different encryption concepts. Just skip until &lt;a href=&#34;#5&#34;&gt;What is GPG?&lt;/a&gt; (in there are two sub sections about &amp;ldquo;OpenSSH&amp;rdquo;, &amp;ldquo;SSH Agent&amp;rdquo; and &amp;ldquo;OpenSSL&amp;rdquo;, just skip those until you get to the next &amp;ldquo;GPG&amp;rdquo; section and continue all the way from there)&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post &lt;strong&gt;isn&amp;rsquo;t&lt;/strong&gt; meant to be &amp;ldquo;this is how you do security&amp;rdquo;. I&amp;rsquo;m not a security expert. I&amp;rsquo;m not even a security intermediate! When I titled this post &amp;ldquo;security basics&amp;rdquo; I wasn&amp;rsquo;t kidding. If you&amp;rsquo;re working with applications and/or servers in production then &lt;em&gt;please&lt;/em&gt; consult someone better equipped on the subject of security.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;although quite a tough read at times, I would highly recommend &amp;ldquo;Bulletproof SSL and TLS&amp;rdquo; written by Ivan Ristić&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now the actual purpose of this post was twofold:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Solidify my own understanding of the tools I&amp;rsquo;ll be covering&lt;/li&gt;&#xA;&lt;li&gt;Helping others to also understand the purposes of said tools&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Security can be confusing. It&amp;rsquo;s taken me longer than I care to admit to really understand the things I&amp;rsquo;ll be discussing here (and even then I&amp;rsquo;ll likely have missed a lot of important nuances), and with that said: what am I planning on covering in this post? Well that would be&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What are keys and how do they work?&lt;/li&gt;&#xA;&lt;li&gt;Understanding PKI&lt;/li&gt;&#xA;&lt;li&gt;OpenSSL vs OpenSSH&lt;/li&gt;&#xA;&lt;li&gt;What is GPG&lt;/li&gt;&#xA;&lt;li&gt;Creating your own keys&lt;/li&gt;&#xA;&lt;li&gt;How to encrypt data using GPG, OpenSSL and Keybase&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;and a lot more inbetween.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;plaintext-and-ciphers&#34;&gt;Plaintext and Ciphers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Throughout this post you&amp;rsquo;ll see me use words like &amp;ldquo;plaintext&amp;rdquo; and &amp;ldquo;cipher&amp;rdquo;. It&amp;rsquo;s important to know what these mean before moving on, so let&amp;rsquo;s clarify this now:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a file is said to be plaintext it simply means that it&amp;rsquo;s unencrypted, whereas a cipher is a noun that refers to a plaintext that has been encrypted. That&amp;rsquo;s it.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-are-keys-and-how-do-they-work&#34;&gt;What are keys and how do they work?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a plaintext file which contains a password, and you want to share this file with someone else across the internet (let&amp;rsquo;s say this someone is our friend &amp;ldquo;Bob&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You could open an email (or chat program), attach the file and send it to Bob. But this isn&amp;rsquo;t very safe because you could have some devious person &amp;lsquo;sniffing&amp;rsquo; your network traffic, picking up your communication and subsequently stealing the plaintext file containing the password you&amp;rsquo;d rather they not get access to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To prevent this devious person from being able to see the password we would need to &lt;em&gt;encrypt&lt;/em&gt; the plaintext document into a cipher and to transfer the cipher instead of the plaintext, meaning if anyone was to interrupt your communication then they would get the cipher and it would be unreadable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to encrypt the plaintext into a cipher we need to use a technique that relies on the concept of a &amp;ldquo;key&amp;rdquo;. A key is a mathematical algorithm for turning plaintext into seemingly random alphanumeric characters. A key can be used to both encrypt and decrypt plaintext.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the longer the key, the more secure the encryption will be. This is why, when generating keys, you&amp;rsquo;ll typically be asked to provide the key size (e.g. 128-bit) you want to use for your encryption key&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But in order for your recipient (Bob in this case) to know how to &lt;em&gt;decrypt&lt;/em&gt; the cipher you&amp;rsquo;ve sent to them, they also need to know the key you&amp;rsquo;ve used.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how do you let the intended recipient (Bob) know the algorithm you&amp;rsquo;ve used? You can&amp;rsquo;t just email them and say &amp;ldquo;I&amp;rsquo;ve used algorithm X to turn this plaintext document into a cipher&amp;rdquo;, because the same devious person who originally sniffed your network traffic and grabbed your cipher will also be able to sniff this additional communication and learn the algorithm (i.e. the key) that was used to encrypt the plaintext; allowing them to decrypt your cipher and to retrieve your super secret password.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;public-key-cryptography&#34;&gt;Public-key cryptography&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To resolve the issue of not being able to safely communicate an encryption key, some clever people designed a scheme known as &amp;ldquo;public-key cryptography&amp;rdquo;. The principle idea being that you generate two keys:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;A public key&lt;/li&gt;&#xA;&lt;li&gt;A private key&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;As you can probably already guess, the &amp;ldquo;public&amp;rdquo; key is something that is safe to become public (i.e. if some devious person got a hold of your public key then it&amp;rsquo;s not that much of an issue), while the &amp;ldquo;private&amp;rdquo; key is something you should keep hidden and not share with anyone (it&amp;rsquo;s very important you protect this file).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But how exactly do these two keys help our situation?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Well, the keys are the mathematical &lt;em&gt;inverse&lt;/em&gt; of each other; which means you can encrypt data with either the public or private key, and only the alternating key can be used to decrypt the data. So if you encrypted a plaintext using your public key, then the only way you can decrypt the resulting cipher is by using your private key. But imagine you encrypted a file using your public key: as your private key is something only &lt;em&gt;you&lt;/em&gt; have access to it means your cipher is safe from everyone! (as long as your private key stays private)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now that we have a basic understanding of public-key cryptography, you should be able to see how this can be used to keep our ciphers safe from being decrypted by unintended devious type people. So let&amp;rsquo;s go back to our previous example where we have a plaintext document that we want to encrypt and only share with our friend Bob&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;public-key-example&#34;&gt;Public-key example&lt;/h3&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this example is INSECURE and I explain why afterwards&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In this example there are two prerequisites:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;We&amp;rsquo;ve generated our own public/private keys&lt;/li&gt;&#xA;&lt;li&gt;Bob has generated his own public/private keys&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;With a basic understanding of public-key cryptography, the steps involved appear quite straightforward:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We email Bob and ask him for his public key&lt;/li&gt;&#xA;&lt;li&gt;Bob emails us his public key&lt;/li&gt;&#xA;&lt;li&gt;We encrypt our plaintext using Bob&amp;rsquo;s public key&lt;/li&gt;&#xA;&lt;li&gt;We email Bob the cipher created using his public key&lt;/li&gt;&#xA;&lt;li&gt;Bob receives the cipher and uses his private key to decrypt it&lt;/li&gt;&#xA;&lt;li&gt;Bob now has a copy of the original plaintext&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In an ideal world these steps are fine, but we don&amp;rsquo;t live in an ideal world. Now you may have already noticed the problem with this process, but if not I&amp;rsquo;ll clarify why this isn&amp;rsquo;t secure: the devious network sniffer has intercepted your email communication asking Bob for his public key and the devious person sends back his own public key instead. So at this point you get a public key that you think is Bob&amp;rsquo;s but which actually belongs to the devious person.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when you go to send the cipher back to Bob, the devious person sees your communication going across the wire and intercepts it again and grabs the cipher and is able to decrypt it using his private key and subsequently gets access to the plaintext!&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;authentication&#34;&gt;Authentication&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We arrive at yet another security problem with encrypting data, and although using something like public-key cryptography helps it doesn&amp;rsquo;t solve the issue of &amp;ldquo;authentication&amp;rdquo;. By this we mean: how to do we know the person we&amp;rsquo;re communicating with is really who they say they are?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You might think for everyone to securely identify themselves they could publish their public keys online. This would mean instead of people having to provide you with their public key via an insecure communication channel, they could point you to a secure location where their public key resides. This is where a service such as &lt;a href=&#34;https://keybase.io/&#34; target=&#34;_blank&#34;&gt;https://keybase.io/&lt;/a&gt; comes in (this is still in preview). There are also more traditional services that you can use, such as: &lt;a href=&#34;http://keyserver.ubuntu.com:11371/&#34; target=&#34;_blank&#34;&gt;keyserver.ubuntu.com&lt;/a&gt;, &lt;a href=&#34;http://pgp.mit.edu/&#34; target=&#34;_blank&#34;&gt;pgp.mit.edu&lt;/a&gt; and &lt;a href=&#34;https://keyserver.pgp.com/vkd/GetWelcomeScreen.event&#34; target=&#34;_blank&#34;&gt;keyserver.pgp.com&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;You can access my public key here: &lt;a href=&#34;https://keybase.io/integralist&#34; target=&#34;_blank&#34;&gt;keybase.io/integralist&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;But unless you&amp;rsquo;re talking (in real-life or over the phone) with the actual person you want to communicate with, then how do you &lt;em&gt;really&lt;/em&gt; know who published the key was the person you think it is? Authenticating people is a difficult problem to solve and this is where PKI (Public-key infrastructure) comes in.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;understanding-pki&#34;&gt;Understanding PKI&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Public key infrastructure is built on top of Public-key cryptography. The difference is that PKI introduces the concept of &amp;ldquo;certificates&amp;rdquo;, and these certificates are used in the software realm much like we would use a passport.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the real world, the government is a trusted authority (ok so maybe that&amp;rsquo;s questionable nowadays, but go along with it please&amp;hellip;) and they issue you a passport which contains details and information that uniquely identifies you. In the digital world, a certificate does much the same thing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now at this point it&amp;rsquo;s worth pointing out that certificates are designed to identify websites rather than people and so PKI is built on the premise that you are communicating with a domain/web server. They don&amp;rsquo;t really help us with regards to the problem we had earlier with transferring a cipher securely (I&amp;rsquo;ll come back to that issue later).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;technically certificates are created using the &lt;a href=&#34;https://en.wikipedia.org/wiki/X.509&#34; target=&#34;_blank&#34;&gt;X.509 standard&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What PKI can do is help verify the communication between you (e.g. your web browser) and another website is handled securely and is happening with the correct/relevant endpoint. This is useful because if you&amp;rsquo;re doing some online banking, you want to be sure that communication between you and the bank are happening privately/securely without anyone being able to sniff your information over the wire. But also, you want to be sure you&amp;rsquo;re communicating with your bank and not some devious endpoint &lt;em&gt;pretending&lt;/em&gt; to be your bank but in fact is getting you to type in your account and password details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way that PKI manages the ability to authenticate an endpoint (i.e. some website/service you&amp;rsquo;re communicating with) is through the use of certificates. When you visit a website you&amp;rsquo;ll use either the http or https protocols. The latter is what signifies a secure connection. When using https, if the website has a valid certificate, then your browser knows that the communication is happening with the right website.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how can you trust a certificate? Surely someone can set up a website that looks like your bank, then create a certificate and associate it with their website domain? Yes this is possible; but the idea of PKI is that it is built upon a &amp;ldquo;web of trust&amp;rdquo;. Let me clarify what that means&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;certificate-authorities-cas&#34;&gt;Certificate Authorities (CAs)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Your web browser has a list of organisations it &lt;em&gt;trusts&lt;/em&gt; (known as a &amp;ldquo;CA&amp;rdquo; or &amp;ldquo;Certificate Authority&amp;rdquo;), and these organisations can issue certificates.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a website uses a certificate that has not been issued (i.e. &amp;ldquo;signed&amp;rdquo;) by one of these trusted CAs, then your web browser will display a warning that you probably shouldn&amp;rsquo;t continue on to the website as it doesn&amp;rsquo;t appear to be who it says it is (i.e. the website &lt;em&gt;could&lt;/em&gt; be who they say they are - your bank - but we can&amp;rsquo;t really trust them because the certificate they&amp;rsquo;ve presented to us wasn&amp;rsquo;t issued by a CA we know of).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;certificates are created and then &amp;ldquo;signed&amp;rdquo; using an encrypted signature. This is done using the CAs private key. Because the CAs public key is, well&amp;hellip; public, it means our browser can use the public key to verify that the certificate it is presented by a website was indeed issued by a CA we trust and wasn&amp;rsquo;t created by some devious person/organisation instead&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So where do these trusted organisations come from? Well as you can imagine, there is a very high cost and detailed process involved with becoming an authorised CA. This is because we have to implicitly trust them to look after our best interests (and only issue certificates to companies/organisations who have proved their true identity through the CAs own rigorous registration process).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;intermediate-cas&#34;&gt;Intermediate CAs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now CAs will sometimes create &amp;ldquo;intermediate&amp;rdquo; CAs. These are organisations who can issue certificates on behalf of the original CA (also known as the &amp;ldquo;Root CA&amp;rdquo;). If you go to a website that has a certificate, you can inspect the certificate to verify whether it was issued by a root CA or by an intermediate CA. If the certificate came from an intermediate CA, then you can follow the thread back to the root (the web browser typically handles this verification check for you).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the reasons this is done is because the root CA is very very important. It has the power to issue certificates and so if the private key ever fell into the wrong hands, then it could be used to generate certificates for all sorts of domains/websites that weren&amp;rsquo;t who they claimed to be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the real world, once a root CA is set-up, the private key is stored offline. For example, the hard drive the private key is stored on is extracted from the computer and stored in a fire safe (even input ports are filled with glue, preventing someone from stealing the drive and trying to extract the data). Serious business this CA stuff!&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;certificate-revocation-list-crls&#34;&gt;Certificate Revocation List (CRLs)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Certificates are issued with a validity period (expiration date). Every time your browser interrogates a site&amp;rsquo;s certificate, it is checking the certs validity period. If the date for the validity period has passed, then the browser will warn you that the certificate is now expired.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At the same time though, if the certificate hasn&amp;rsquo;t expired, then your browser will consult its Certificate Revocation List to see if the certificate has been revoked. This CRL is downloaded by your browser/operating system on a regular basis and there in lies the problem with CRLs: they&amp;rsquo;re not real-time results.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine a certificate was issued for the website &lt;code&gt;www.foo.com&lt;/code&gt;, but later needed to be revoked (for whatever nefarious reason). In this scenario the CRL is updated to state the website &lt;code&gt;www.foo.com&lt;/code&gt; has a revoked certificate and so it cannot be trusted. But because the CRL has to be downloaded in order to see the updated list, the user (you) could end up visiting the website before you had the new CRL and so the certificate would still be seen to be valid.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because of the lack of real-time validation checking, the Online Certificate Status Protocol (OCSP) has superseded CRLs in that it is (as the name would suggest) an online resource which systems can query at run-time to verify the validity of a certificate.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;ssl-and-tls&#34;&gt;SSL and TLS&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So far we&amp;rsquo;ve been talking about certificates being the solution to how we can authenticate a server&amp;rsquo;s identity, and PKI as the overarching process for helping us to secure that communication (using public-key cryptography under the covers).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To help PKI achieve its goals, a cryptographic protocol was designed called SSL (Secure Socket Layers). This protocol was subsequently superseded by a new protocol called TLS (Transport Layer Security). PKI uses these protocols to enable the secure communication.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you might wonder why you don&amp;rsquo;t hear the phrase TLS used much, and instead see SSL referenced everywhere on the internet when talking about PKI security? This is just an unfortunate case of SSL having become a marketing term that most people can recognise and understand. The majority of the time if someone mentions they have SSL enabled, then what they probably really mean is that they&amp;rsquo;re using the TLS protocol&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;ssl-handshake-cipher-suites-and-key-exchanges&#34;&gt;SSL handshake (Cipher Suites and Key Exchanges)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In order to secure the communication between the client and the server, PKI uses the stages defined within its protocol to fufil what&amp;rsquo;s commonly referred to as the &amp;ldquo;SSL handshake&amp;rdquo;. This is a set of communicative steps taken between the client (your web browser) and the server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember from earlier we discussed how public-key cryptography works and that with it we can secure the communication channel; but at this point we&amp;rsquo;re still not sure how that happens without exposing the encryption key (necessary to encrypt our data back and forth across the wire) to any devious people sniffing our network traffic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As we&amp;rsquo;ll see in a moment, one of the steps in the SSL handshake is called the &amp;ldquo;key exchange&amp;rdquo;; this exchange between the client/server is for the encryption key, and is done using a public-key cryptography algorithm. The most popular choice (at the time of writing) is the &lt;a href=&#34;https://en.wikipedia.org/wiki/RSA_(cryptosystem)&#34; target=&#34;_blank&#34;&gt;RSA algorithm&lt;/a&gt;, which uses the server&amp;rsquo;s public key (provided in the certificate the server sends to the client) to encrypt the key before sending it to the server.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re using the &lt;a href=&#34;https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange&#34; target=&#34;_blank&#34;&gt;Diffie–Hellman key exchange algorithm&lt;/a&gt; you&amp;rsquo;ll find a great visual explanation of the process which uses the analogy of &amp;ldquo;mixing colours&amp;rdquo; to indicate the maths behind the equation (e.g. easy to calculate in one direction, but very difficult to reverse; much like mixing two colours together is easy, but unmixing would be quite arduous). There are also performance penalties associated with some more advanced key exchange algorithms that you need to take into consideration&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In order for the SSL handshake to proceed successfully, the client needs to provide the server with some preliminary options; one being a &amp;ldquo;cipher suite&amp;rdquo;. A cipher suite has a structure that looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;TLS_RSA_WITH_AES_128_CBC_SHA&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This might just look like a jumble of acronyms, so let&amp;rsquo;s break down what this means:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;TLS: the protocol&#xA;RSA: the key exchange algorithm&#xA;AES: the encryption algorithm&#xA;128: the encryption strength&#xA;CBC: the encryption mode&#xA;SHA: the hash function for a digital signature&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example, we use &lt;code&gt;RSA&lt;/code&gt; which is interpreted as &lt;em&gt;both&lt;/em&gt; the key exchange algorithm AND the authentication mechanism. But with other cipher suites you&amp;rsquo;ll see two separate values (e.g. &lt;code&gt;DHE_RSA&lt;/code&gt; where &lt;code&gt;DHE&lt;/code&gt; is the key exchange and &lt;code&gt;RSA&lt;/code&gt; is the authentication mechanism).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The client supports various different cipher suites and so it&amp;rsquo;ll send all of the different variations it is happy to handle, while the server&amp;rsquo;s job is to find the most secure match and respond to confirm the cipher suite it has selected.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;cipher suites are just one (of many) areas of communication open to a MITM (man-in-the-middle) attack. For example, a devious network sniffer intercepts your initial insecure communication with a server and removes all the cipher suites leaving only the weakest one. The server has no option but to select the one and only cipher suite left, meaning the attacker has an easier time brute forcing through the weaker encryption methods&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;One other item we&amp;rsquo;ll want to be aware of is what&amp;rsquo;s called a MAC (&lt;a href=&#34;https://en.wikipedia.org/wiki/Message_authentication_code&#34; target=&#34;_blank&#34;&gt;Message Authentication Code&lt;/a&gt;). The MAC is a way of ensuring authentication and integrity by combining an agreed key and a hashing cipher to create a signature for some content. If we send some data we&amp;rsquo;ll also send a MAC with it and because both sides have the key/cipher information we can ensure the message content hasn&amp;rsquo;t been tampered with. We&amp;rsquo;ll see in just a moment that one of our handshake steps will be for the client/server to verify each other using a MAC.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a quick look at the SSL handshake (this isn&amp;rsquo;t exhaustive, and I&amp;rsquo;ve left out lots of steps for brevity):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Client sends cipher suite, a random number, a protocol version and list of compression methods&lt;/li&gt;&#xA;&lt;li&gt;Server sends back a selected cipher suite (most secure match), a random number, the protocol version it supports and a selected compression method&lt;/li&gt;&#xA;&lt;li&gt;Client requests certificate for identification **&lt;/li&gt;&#xA;&lt;li&gt;Server sends its certificate&lt;/li&gt;&#xA;&lt;li&gt;Client sends a &amp;ldquo;premaster secret&amp;rdquo; encrypted using the key exchange algorithm defined in the selected cipher suite&lt;/li&gt;&#xA;&lt;li&gt;Server decrypts the premaster secret&lt;/li&gt;&#xA;&lt;li&gt;Both client/server can generate a &amp;ldquo;master secret&amp;rdquo; using both sets of random numbers previously sent to each other&lt;/li&gt;&#xA;&lt;li&gt;Client/Server uses the master secret to derive the encryption keys used to encrypt all future communication&lt;/li&gt;&#xA;&lt;li&gt;Client sends a MAC of the communication so far&lt;/li&gt;&#xA;&lt;li&gt;Server creates a MAC and compares with Client MAC (if the same then Server switches to encryption)&lt;/li&gt;&#xA;&lt;li&gt;Server tells the client it&amp;rsquo;s ready for secure messages&lt;/li&gt;&#xA;&lt;li&gt;Client sends secure mesage(s)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;example-messages&#34;&gt;Example messages&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the previous sub section I briefly ran through the different steps the client and server take in order to communicate securely with each other. But I&amp;rsquo;d like to add onto that some &lt;em&gt;examples&lt;/em&gt; of these messages.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;these examples are copied verbatim from the excellent book &amp;ldquo;Bulletproof SSL and TLS&amp;rdquo; written by Ivan Ristić&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Here is the first example, this is the client opening communication with the server:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Handshake protocol: ClientHello&#xA;    Version: TLS 1.2&#xA;    Random&#xA;        Client time: May 22, 2030 02:43:46 GMT&#xA;        Random bytes: b76b0e61829557eb4c611adfd2d36eb232dc1332fe29802e321ee871&#xA;    Session ID: (empty)&#xA;    Cipher Suites&#xA;        Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256”&#xA;        Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256&#xA;        Suite: TLS_RSA_WITH_AES_128_GCM_SHA256&#xA;        Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA&#xA;        Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA&#xA;        Suite: TLS_RSA_WITH_AES_128_CBC_SHA&#xA;        Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA&#xA;        Suite: TLS_RSA_WITH_RC4_128_SHA&#xA;    Compression methods&#xA;        Method: null&#xA;    Extensions&#xA;        Extension: server_name&#xA;            Hostname: www.feistyduck.com&#xA;        Extension: renegotiation_info&#xA;        Extension: elliptic_curves&#xA;            Named curve: secp256r1&#xA;            Named curve: secp384r1&#xA;        Extension: signature_algorithms&#xA;            Algorithm: sha1/rsa&#xA;            Algorithm: sha256/rsa&#xA;            Algorithm: sha1/ecdsa&#xA;            Algorithm: sha256/ecdsa”&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, all the ingredients are there as we described earlier; the cipher suite being the most important to take note of at this time. Let&amp;rsquo;s move on and see what the server&amp;rsquo;s response would typically look like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Handshake protocol: ServerHello&#xA;    Version: TLS 1.2&#xA;    Random&#xA;        Server time: Mar 10, 2059 02:35:57 GMT”&#xA;        Random bytes: 8469b09b480c1978182ce1b59290487609f41132312ca22aacaf5012&#xA;    Session ID: 4cae75c91cf5adf55f93c9fb5dd36d19903b1182029af3d527b7a42ef1c32c80&#xA;    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256&#xA;    Compression method: null&#xA;    Extensions&#xA;        Extension: server_name&#xA;        Extension: renegotiation_info”&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here we can see the server has sent back its random data (used to construct the premaster secret) and also we can see which cipher suite it has selected to be used.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;verify-ssl&#34;&gt;Verify SSL&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes you might need to debug an issue with your SSL connection. In order to do that you&amp;rsquo;ll want to utilise the OpenSSL utility command &lt;code&gt;s_client&lt;/code&gt;. This will allow you to open a connection to your host using the SSL/TLS protocol of your choice and control the various different configuration settins.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A basic example would be as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl s_client -connect google.com:443 -showcerts&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll see we&amp;rsquo;re connecting to Google (which is secured using SSL/TLS) and we also specify the &lt;code&gt;-showcerts&lt;/code&gt; flag, which allows the response to display all certificates provided within the chain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The response looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;CONNECTED(00000003)&#xA;depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA&#xA;verify error:num=20:unable to get local issuer certificate&#xA;verify return:0&#xA;---&#xA;Certificate chain&#xA; 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com&#xA;   i:/C=US/O=Google Inc/CN=Google Internet Authority G2&#xA;-----BEGIN CERTIFICATE-----&#xA;MIIHjTCCBnWgAwIBAgIIGo+tp3jIDvEwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE&#xA;BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl&#xA;cm5ldCBBdXRob3JpdHkgRzIwHhcNMTUxMDE1MTY0MTE2WhcNMTYwMTEzMDAwMDAw&#xA;WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN&#xA;TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n&#xA;b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCZxkmtf&#xA;Au04O0RjThQnFAzC27w9VlfAoQrgqPtarJIvQDw4G8NZEUSWIlPr0nGr5z3CicxY&#xA;ddO2+U8vz/aEltcIUDqNNsdordbLLl7zBS2zkDnSZEmJcM5wYM8biJ3FSU3WzRmN&#xA;o8px1LCj49dpQButCJ7FCDIU3eaxZRYZaEiO2UCR7BT8wdyE9O49YKcDUycTgaNu&#xA;pM5oTFPqqj+3mDLZsB8BjIssboE8dutdU0TTY4SJ3EPFsSeVTOFu7WY+s628hwMw&#xA;kw5sy9viYUZf11RL0zleKarvdQ+oE6gK59ilknrrRXONpepKX6cBGwF/cF+Xl4y4&#xA;tjvbvWfNETvmPQIDAQABo4IEWjCCBFYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG&#xA;AQUFBwMCMIIDJgYDVR0RBIIDHTCCAxmCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk&#xA;LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29t&#xA;ghYqLmdvb2dsZS1hbmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUu&#xA;Y2yCDiouZ29vZ2xlLmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28u&#xA;dWuCDyouZ29vZ2xlLmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5j&#xA;b20uYnKCDyouZ29vZ2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2ds&#xA;ZS5jb20udHKCDyouZ29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xl&#xA;LmVzggsqLmdvb2dsZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdv&#xA;b2dsZS5ubIILKi5nb29nbGUucGyCCyouZ29vZ2xlLnB0ghIqLmdvb2dsZWFkYXBp&#xA;cy5jb22CDyouZ29vZ2xlYXBpcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESou&#xA;Z29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CCiou&#xA;Z3Z0MS5jb22CCiouZ3Z0Mi5jb22CFCoubWV0cmljLmdzdGF0aWMuY29tggwqLnVy&#xA;Y2hpbi5jb22CECoudXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5j&#xA;b22CDSoueW91dHViZS5jb22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRp&#xA;bWcuY29tggthbmRyb2lkLmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0&#xA;aWNzLmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4u&#xA;Y29tggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29t&#xA;MGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUu&#xA;Y29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2ds&#xA;ZS5jb20vb2NzcDAdBgNVHQ4EFgQUpypq8xCS2PlWTuyHYX7xgHb9UgwwDAYDVR0T&#xA;AQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAhBgNVHSAE&#xA;GjAYMAwGCisGAQQB1nkCBQEwCAYGZ4EMAQICMDAGA1UdHwQpMCcwJaAjoCGGH2h0&#xA;dHA6Ly9wa2kuZ29vZ2xlLmNvbS9HSUFHMi5jcmwwDQYJKoZIhvcNAQELBQADggEB&#xA;AFRzPPSVNMFRDoePYeOs7awHmRpp79v7loOBMO7ctrTjpfhVjPsQmvzDlfEken2q&#xA;HMs/r76I0s7E4hk6v2ZNFiDjSnnHvjIGG1PydfEVovL/FqsX3kUaWqqCeymGcwRC&#xA;ld2F6XqgKkPRf00DjbnFmDKGpRyEMQd91HoutzSMSypPqFCNSpVGuPFP32D1+/Vh&#xA;oukY3gGUlNGukoJ2e/VNnRrU7NBvyGkW83CGPMR2iwwa0/7aVGs1iy4aypaBo+0q&#xA;QxFmxwn1AWJYyhFbsdfrhf3ux8KEQGDEIHOSa9+SjL/GYQENXGfkVIj/OG1KV0CB&#xA;K8pC8t/AFLMrBFjS1gbkE7U=&#xA;-----END CERTIFICATE-----&#xA; 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2&#xA;   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA&#xA;-----BEGIN CERTIFICATE-----&#xA;MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT&#xA;MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i&#xA;YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG&#xA;EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy&#xA;bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB&#xA;AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP&#xA;VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv&#xA;h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE&#xA;ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ&#xA;EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC&#xA;DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7&#xA;qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD&#xA;VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov&#xA;L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig&#xA;JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ&#xA;MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+&#xA;3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI&#xA;hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI&#xA;Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X&#xA;Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm&#xA;X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40&#xA;fsg12A==&#xA;-----END CERTIFICATE-----&#xA; 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA&#xA;   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority&#xA;-----BEGIN CERTIFICATE-----&#xA;MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT&#xA;MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0&#xA;aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw&#xA;WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE&#xA;AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB&#xA;CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m&#xA;OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu&#xA;T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c&#xA;JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR&#xA;Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz&#xA;PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm&#xA;aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM&#xA;TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g&#xA;LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO&#xA;BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv&#xA;dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB&#xA;AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL&#xA;NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W&#xA;b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S&#xA;-----END CERTIFICATE-----&#xA;---&#xA;Server certificate&#xA;subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com&#xA;issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2&#xA;---&#xA;No client certificate CA names sent&#xA;---&#xA;SSL handshake has read 4021 bytes and written 456 bytes&#xA;---&#xA;New, TLSv1/SSLv3, Cipher is AES128-SHA&#xA;Server public key is 2048 bit&#xA;Secure Renegotiation IS supported&#xA;Compression: NONE&#xA;Expansion: NONE&#xA;SSL-Session:&#xA;    Protocol  : TLSv1&#xA;    Cipher    : AES128-SHA&#xA;    Session-ID: C9BC3D21CD96713FA4EA7C21D60FF2F5DDBC6C2D2C68543652E9790C7A98DC58&#xA;    Session-ID-ctx: &#xA;    Master-Key: AE3A9EBD53ED49E4FDAABBCF6EA3B4096D9248127BC056CFB1F8981F2A3AB4E8779DC8195241A9A3A25DB03EDAED6077&#xA;    Key-Arg   : None&#xA;    Start Time: 1445868754&#xA;    Timeout   : 300 (sec)&#xA;    Verify return code: 0 (ok)&#xA;---&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What might not be clear at this point is you&amp;rsquo;re still sitting in an interactive mode within the shell and so you can issue additional requests like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;HEAD / HTTP/1.0&#xA;Host: www.google.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;remember to press &lt;code&gt;&amp;lt;Enter&amp;gt;&lt;/code&gt; twice to send the request&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The above sends a request for just the headers for the specified host, and so the response looks something like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;HTTP/1.0 302 Found&#xA;Cache-Control: private&#xA;Content-Type: text/html; charset=UTF-8&#xA;Location: https://www.google.co.uk/?gfe_rd=cr&amp;amp;ei=wzUuVtGjLLDj8wek176wCQ&#xA;Content-Length: 262&#xA;Date: Mon, 26 Oct 2015 14:16:35 GMT&#xA;Server: GFE/2.0&#xA;Alternate-Protocol: 443:quic,p=1&#xA;Alt-Svc: quic=&amp;quot;www.google.com:443&amp;quot;; p=&amp;quot;1&amp;quot;; ma=600,quic=&amp;quot;:443&amp;quot;; p=&amp;quot;1&amp;quot;; ma=600&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following is another example (a non-working example unfortunately), but this time the service we&amp;rsquo;re querying is utilising self-signed certificates, and so we&amp;rsquo;re required to provide the CA as well as our own client certificate for authentication:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl s_client \&#xA;  -connect my-fake-service.com:443 \&#xA;  -CAfile /Users/Integralist/.pki/custom-ca.pem \&#xA;  -cert /Users/Integralist/.pki/Certificate.pem \&#xA;  -key /Users/Integralist/.pki/Certificate.key \&#xA;  -showcerts&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The last example I want to show you is where we try and verify if a particular cipher is disabled (in this case the insecure &lt;code&gt;RC4&lt;/code&gt; cipher):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl s_client -connect blog.mozilla.org:443 -showcerts -cipher RC4-SHA&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Mozilla released a &lt;a href=&#34;https://blog.mozilla.org/security/2015/09/11/deprecating-the-rc4-cipher/&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt; recently that stated they&amp;rsquo;ve discontinued support for this particular cipher. So the above command will return the following output, which indicates a &lt;code&gt;SSL handshake failure&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;57533:&#xA;error:&#xA;14077410:&#xA;SSL routines:&#xA;SSL23_GET_SERVER_HELLO:&#xA;sslv3 alert handshake failure:&#xA;/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-59/src/ssl/s23_clnt.c:&#xA;593:&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;certificate-signature&#34;&gt;Certificate signature&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One way the client and server can authenticate each other&amp;rsquo;s identities is via the MAC they send during the SSL handshake. But the client first verifies the server&amp;rsquo;s identity by checking the certificate provided by the server (also done at the very beginning of the SSL handshake) has not only been signed by a CA we trust, but has also not been modified at any point along the way from the server to the client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The client can do this by inspecting the signature on the certificate. Earlier when we discussed how CAs generate certificates, we mentioned that the CA will &amp;ldquo;sign&amp;rdquo; the certificate. The signature is result of applying a &lt;a href=&#34;https://en.wikipedia.org/wiki/Hash_function&#34; target=&#34;_blank&#34;&gt;hash function&lt;/a&gt; to the contents of the certificate itself and then encrypting that hash value using the CAs private key.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this technique works is because if a devious network sniffer tried to replace the certificate with their own modified version, then the client would be able to tell; and the reason the client can tell the certificate has been tampered with is because the client can verify the certificate by converting it into a hash using the same hash function as the CA used when creating its signature (details of the hashing algorithm are part of the certificate). The client can then decrypt the CAs signature (using the CAs public key) which results in the hash value. The client then compares the two hashes (the one it extracted from the signature, and the one it generated itself from the certificate content) to make sure they match. If they don&amp;rsquo;t match, then we know the certificate has been modified at some point and cannot be trusted.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;pki-conclusion&#34;&gt;PKI Conclusion&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So there you have it, that&amp;rsquo;s pretty much how PKI (and subsequently SSL/TLS) works; although presented in a stripped down way to make this post even remotely bearable to any sane person.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s move on!&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;openssl-vs-openssh&#34;&gt;OpenSSL vs OpenSSH&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you want to generate your own keys and certificates, which will enable you to connect and transmit data more securely across the internet; then you&amp;rsquo;re going to need to install the &lt;a href=&#34;https://openssl.org/&#34; target=&#34;_blank&#34;&gt;OpenSSL&lt;/a&gt; command line toolkit. OpenSSL is a library designed to implement the SSL/TLS protocols&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;openssl&lt;/code&gt; command is a wrapper around the OpenSSL library&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;What you might not be aware of though is how large a suite of cryptographic tools OpenSSL actually provides. Later on in this post we&amp;rsquo;ll demonstrate a tiny selection of these tools in order to create our own keys and encrypt some data; but for now we&amp;rsquo;ll focus more on the differences between OpenSSL and OpenSSH.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So where OpenSSL is designed to provide a method for securing web based communication; &lt;a href=&#34;http://www.openssh.com/&#34; target=&#34;_blank&#34;&gt;OpenSSH&lt;/a&gt; on the other hand provides secure and encrypted tunneling capabilities. It is typically used to enable secure shell connections from your machine to external servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OpenSSH has a different transport protocol compared to OpenSSL. Although OpenSSH does actually utilise OpenSSL for its cryptographic operations, such as key pair generation. So as long as you&amp;rsquo;re using the same algorithms for generating keys you&amp;rsquo;ll find no difference between OpenSSH and OpenSSL&amp;rsquo;s level of security in that sense (although there is a larger attack vector with regards to OpenSSH so you could argue it&amp;rsquo;s &lt;em&gt;potentially&lt;/em&gt; more open to security concerns as attackers have more options available to them).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the suite of command line tools people typically associate with OpenSSH are actually commands designed &lt;em&gt;around&lt;/em&gt; the OpenSSH protocol standard (i.e. there isn&amp;rsquo;t an actual &lt;code&gt;openssh&lt;/code&gt; command; and as such, OpenSSH is just the &amp;lsquo;protocol&amp;rsquo; and &lt;em&gt;not&lt;/em&gt; the command line tools themselves)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;openssh-utilities&#34;&gt;OpenSSH utilities&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are a few different tools available within OpenSSH and although (later on in the section where we learn how to generate our own keys) we&amp;rsquo;ll be using the command line tools, we&amp;rsquo;ll primarily be focusing on the &lt;code&gt;ssh-keygen&lt;/code&gt; command along with demonstrating how I use &lt;code&gt;ssh-agent&lt;/code&gt; and &lt;code&gt;ssh-add&lt;/code&gt; to make working with OpenSSH a little easier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are a list of tools that are built upon the OpenSSH protocol:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ssh-keygen&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ssh-agent&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ssh-add&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ssh-keysign&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ssh-keyscan&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sftp-server&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sshd&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-gpg&#34;&gt;What is GPG?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://gnupg.org/&#34; target=&#34;_blank&#34;&gt;GPG&lt;/a&gt; is a tool which provides encryption and signing capabilities. Its full name is &amp;ldquo;GNU Privacy Guard&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;GPG supports both symmetrical and asymmetrical encryption techniques along with an optional digital signing of your encrypted content to ensure integrity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the next section &amp;ldquo;&lt;a href=&#34;#6&#34;&gt;Creating your own keys&lt;/a&gt;&amp;rdquo; I&amp;rsquo;ll demonstrate how to actually use GPG.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;gpg-vs-pgp&#34;&gt;GPG vs PGP&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You may have also heard of PGP and wondered what the differences are between that and GPG: PGP is the protocol standard (defined under the name &amp;ldquo;Open PGP&amp;rdquo;) which GPG implements. So PGP isn&amp;rsquo;t a tool itself, but merely a specification for other tools (such as GPG) to build upon.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;creating-your-own-keys&#34;&gt;Creating your own keys&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, up until this point we&amp;rsquo;ve only been talking in a theorectical sense. Time to see some pratical use cases by demonstrating how to generate your own keys using the three different toolkits we&amp;rsquo;ve described up until this point (OpenSSH, OpenSSL and GPG).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m going to quickly run through each utility (OpenSSH, OpenSSL and GPG) and explain how you can create your own keys for each of them. I wont go into great detail the flags/settings used in each example command as that is what the &lt;code&gt;man&lt;/code&gt; command is for (i.e. I&amp;rsquo;ll leave investigation of these settings as an exercise for the reader).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, generating keys is one thing. But for the OpenSSL and GPG utilities, it&amp;rsquo;s not until we need to actually encrypt some data (see the next section &amp;ldquo;&lt;a href=&#34;#7&#34;&gt;How to encrypt data using GPG, OpenSSL and Keybase&lt;/a&gt;&amp;rdquo;) that these keys can become useful (OpenSSH is another beast altogether).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s begin&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;openssh&#34;&gt;OpenSSH&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the following example we&amp;rsquo;re generating a new set of keys (public and private) using the RSA type and using 4096 bits for the key length. This is considered quite a secure set-up (anything less than 2048 bits is easily crackable in todays digital age):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C &amp;quot;your.email@service.com&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Running this command you&amp;rsquo;ll be asked to provide a name for the keys and an (optional) password. Once this is done you&amp;rsquo;ll find two files in the current directory (imagine we named the key &lt;code&gt;foo_rsa&lt;/code&gt; when prompted):&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;foo_rsa&lt;/code&gt;: contains your private key&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;foo_rsa.pub&lt;/code&gt;: contains your public key&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can change the passphrase associated with your private key by running &lt;code&gt;ssh-keygen -p&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now we have these keys, we can provide our public key to an external service such as &lt;a href=&#34;https://help.github.com/articles/generating-ssh-keys/&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt; or have them installed on a remote server. Either way this will allow us to connect our shell securely to these remote services/servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of connecting to a remote server, you would have your devops or operations people add your public key into a &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file (or you could do it yourself: &lt;code&gt;cat foo_rsa.pub | ssh user@123.45.56.78 &amp;quot;mkdir -p ~/.ssh &amp;amp;&amp;amp; cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys&amp;quot;&lt;/code&gt;). Once your public key is added you&amp;rsquo;ll be able to securely connect to the server without requiring your password because your private key will be used to authenticate your access.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;convention is for SSH keys to be placed inside a &lt;code&gt;~/.ssh&lt;/code&gt; folder&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;One final change that can be made on your remote server (again, this could be handled by your devops or operations team) is to restrict logins to your server to &lt;em&gt;only&lt;/em&gt; happen via SSH keys. To do this you need to log into the server and change the file &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; by locating the line that specifies &lt;code&gt;PermitRootLogin&lt;/code&gt; and changing its value like so: &lt;code&gt;PermitRootLogin without-password&lt;/code&gt;. From there you would run &lt;code&gt;reload ssh&lt;/code&gt; for the changes to take immediate effect.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to find the fingerprint of your SSH key use:&lt;br&gt;&#xA;&lt;code&gt;ssh-keygen -E md5 -lf ~/.ssh/your_rsa.pub&lt;/code&gt;&lt;br&gt;&#xA;The &lt;code&gt;-E md5&lt;/code&gt; provides output as shown by GitHub/GitLab&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;ssh-agent&#34;&gt;SSH Agent&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Most operating systems have &lt;code&gt;ssh-agent&lt;/code&gt; available. If you&amp;rsquo;ve got &lt;code&gt;ssh-keygen&lt;/code&gt; installed, then chances are you&amp;rsquo;ll have the agent and other OpenSSH tools as well. The agent is used to store private keys used for public key authentication. It makes using SSH easier (a trade-off of security for convenience) by allowing you to specify your private key password once.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I&amp;rsquo;m setting up my SSH keys for using GitHub I&amp;rsquo;ll typically run the following commands:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cd ~/.ssh&#xA;ssh-keygen -t rsa -b 4096 -C &amp;quot;my.email@domain.com&amp;quot; # saved as github_rsa&#xA;eval &amp;quot;$(ssh-agent -s)&amp;quot;&#xA;ssh-add -K ~/.ssh/github_rsa&#xA;pbcopy &amp;lt; ~/.ssh/github_rsa.pub&#xA;ssh -T git@github.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So what&amp;rsquo;s happening here is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I move into the relevant directory where my SSH keys are located&lt;/li&gt;&#xA;&lt;li&gt;Generate my SSH keys (saved as &lt;code&gt;github_rsa&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Start the SSH Agent&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;ssh-add&lt;/code&gt; to add my private key to the agent&lt;/li&gt;&#xA;&lt;li&gt;Copy my public key (and manually paste it into the GitHub GUI)&lt;/li&gt;&#xA;&lt;li&gt;Verify the setup&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I also use the &lt;code&gt;-K&lt;/code&gt; flag with &lt;code&gt;ssh-add&lt;/code&gt; as that&amp;rsquo;s specific to Mac OS X&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;openssl&#34;&gt;OpenSSL&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Like with the OpenSSH example in the previous sub section, here we&amp;rsquo;ll be generating a new set of keys (public and private) using the RSA type and using 4096 bits for the key length. The difference is that you have to generate the private key first and then extract the public key from it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl genrsa -out private_key.pem 4096&#xA;openssl rsa -pubout -in private_key.pem -out public_key.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also print out some additional details contained inside your pem file by using the &lt;code&gt;-text&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl rsa -text -in private_key.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;gpg&#34;&gt;GPG&lt;/h3&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://alexcabal.com/creating-the-perfect-gpg-keypair/&#34; target=&#34;_blank&#34;&gt;here is a great and detailed article&lt;/a&gt; on how to make the most secure key pair process possible&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Generating a key pair with GPG is a little bit more involved as you have some prompts you need to step through. The command to begin with is:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --gen-key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will present the following information:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Please select what kind of key you want:&#xA;(1) RSA and RSA (default)&#xA;(2) DSA and Elgamal&#xA;(3) DSA (sign only)&#xA;(4) RSA (sign only)&#xA;Your selection? &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll then be asked the key length (I entered 4096 to match other keys I&amp;rsquo;ve created):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;RSA keys may be between 1024 and 4096 bits long.&#xA;What keysize do you want? (2048) &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;After this you&amp;rsquo;ll be asked to provide an expiration date (I picked 1 year):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Requested keysize is 4096 bits       &#xA;Please specify how long the key should be valid.&#xA;         0 = key does not expire&#xA;      &amp;lt;n&amp;gt;  = key expires in n days&#xA;      &amp;lt;n&amp;gt;w = key expires in n weeks&#xA;      &amp;lt;n&amp;gt;m = key expires in n months&#xA;      &amp;lt;n&amp;gt;y = key expires in n years&#xA;Key is valid for? (0)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Finally, you&amp;rsquo;ll need to input some personal details. I wont add those here, I&amp;rsquo;ll just let you fill those in as needed. It&amp;rsquo;s also worth being aware that GPG will use your system&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Entropy_(computing)&#34; target=&#34;_blank&#34;&gt;entropy&lt;/a&gt; to aid its random number generation, so for a brief moment you&amp;rsquo;ll see it request that you move your cursor around a bit to help build up the entrophy output.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you could also provide all these details via an &amp;lsquo;input&amp;rsquo; file (useful if you find yourself generating lots of key pairs), but that&amp;rsquo;s a bit outside the scope of what we want to focus on here. If you&amp;rsquo;re interested, you can find the &lt;a href=&#34;https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html&#34; target=&#34;_blank&#34;&gt;details here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now before we go any further, it&amp;rsquo;s important that at this point you now generate a revocation certificate:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --gen-revoke my.email@domain.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll want to put this certificate into a file and store it somewhere very safe in case you need to ever revoke your key pair. Preferably you print it out on paper and put it in a fireproof safe.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you ever need to, you can then import the certificate into your keyring and that will immediately revoke your key pair:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --import revocation.cert&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then also push up your key identifier to a key server to force it to recognise the key has been revoked:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --keyserver pgp.mit.edu --send-keys 123456&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once your key pair has been generated you&amp;rsquo;ll probably be confused as to where they&amp;rsquo;re stored? If you were to &lt;code&gt;ls&lt;/code&gt; the current directory they wont be there. Instead you&amp;rsquo;ll need to use the following command to see what public keys you&amp;rsquo;ve generated:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --list-keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For me this displays the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/Users/M/.gnupg/pubring.gpg&#xA;---------------------------&#xA;pub   4096R/056C9716 2015-08-14 [expires: 2016-08-13]&#xA;uid                  Mark McDonnell (Hi) &amp;lt;my.email@domain.com&amp;gt;&#xA;sub   4096R/A1F3D5B6 2015-08-14 [expires: 2016-08-13]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is an equivalent command for viewing your private keys &lt;code&gt;gpg --list-secret-keys&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You can see there is a file &lt;code&gt;pubring.gpg&lt;/code&gt; that appears to contain the details of all the keys I&amp;rsquo;ve created, and interestingly the file itself is protected; so if I try something like &lt;code&gt;cat ~/.gnupg/pubring.gpg&lt;/code&gt; it&amp;rsquo;ll spew out encrypted cipher text at me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to see your public key, then use the following command (notice I&amp;rsquo;ve specified the same name as seen from the above output from &lt;code&gt;--list-keys&lt;/code&gt;; if I tried to specify something else then it wouldn&amp;rsquo;t find any key to export):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --export --armor &amp;quot;Mark McDonnell&amp;quot; &amp;gt; gpg_public.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;--armor&lt;/code&gt; creates ASCII armored output (a text format) instead of raw bytes (binary format)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To get the private key, you&amp;rsquo;ll use a slightly different flag, but effectively it&amp;rsquo;s the same thing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --export-secret-key --armor &amp;quot;Mark McDonnell&amp;quot; &amp;gt; gpg_private.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you have multiple keys under the same name then you&amp;rsquo;ll find that it&amp;rsquo;ll typically export the key for the &lt;em&gt;first&lt;/em&gt; name it finds. To work around this you can specify the email address instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --export --armor my.email@gmail.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;by default it prints to stdout&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the following sections we&amp;rsquo;ll see more of how to use GPG, but it&amp;rsquo;s worth mentioning now that all the settings you use in the command line tool can be set as defaults in a dotfile: &lt;code&gt;~/.gnu/gpg.conf&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if on the command line you used &lt;code&gt;--default-key&lt;/code&gt;, then you could set the following within your &lt;code&gt;gpg.conf&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;default-key 62DBDF62           # Personal&#xA;default-recipient some-user-id # In case you happen to only ever communicate with one person&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;multiple-keys&#34;&gt;Multiple Keys?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Here&amp;rsquo;s a quick question that people seem to ask a lot:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I heard some people have multiple key pairs, one for &amp;lsquo;signing&amp;rsquo; and one for &amp;lsquo;encryption&amp;rsquo;. Why is that?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The answer is that you&amp;rsquo;ll want to rotate your encryption key pair on a regular basis. Ideally you wouldn&amp;rsquo;t have a key pair that never expires or doesn&amp;rsquo;t expire for a very long time because if it becomes compromised (and you&amp;rsquo;re unable to revoke) then you&amp;rsquo;ve got serious problems.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also the company you work for might want to control your encryption key so that once you leave the organisation they can decrypt stuff you&amp;rsquo;ve worked on previously. But if they have your key then you&amp;rsquo;d need to create a new one for your personal interactions and means you couldn&amp;rsquo;t build up a secure and well established identity outside of the company.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In all these cases, it can be easier to just have a separate &amp;lsquo;signing&amp;rsquo; key pair that lasts for a long time. This ultimately becomes your &lt;em&gt;identity&lt;/em&gt; that people trust. You then have separate keys for encrypting and you can digitally sign the encrypted content.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Interestingly by default GPG creates a signing key and an encryption key. You can see this by running the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --list-sigs&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I recommend reading &lt;a href=&#34;https://alexcabal.com/creating-the-perfect-gpg-keypair/&#34; target=&#34;_blank&#34;&gt;https://alexcabal.com/creating-the-perfect-gpg-keypair/&lt;/a&gt; to learn how to create your own sub signing keys and improve the security of your key process/setup.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-to-encrypt-data-using-gpg-openssl-and-keybase&#34;&gt;How to encrypt data using GPG, OpenSSL and Keybase&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Outside of PKI and SSL/TLS, the most common task people are interested in is encrypting specific files that contain sensitive information that they would prefer to be protected either from everyone or allow only a select few people to be able to access. The interface for encrypting data is different for each tool used and so we&amp;rsquo;ll be looking at those we&amp;rsquo;ve discussed so far: GPG and OpenSSL&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;gpg-encryption&#34;&gt;GPG encryption&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;GPG offers two forms of encryption: asymmetrical and symmetrical&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;asymmetrical-encryption&#34;&gt;Asymmetrical encryption&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;With GPG you&amp;rsquo;ll need the recipients public key in order to encrypt files. So once you have the recipients public key you&amp;rsquo;ll need to import it into GPG so you can reference it. To do that you&amp;rsquo;ll use the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --import public.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to delete their public key afterwards, run &lt;code&gt;gpg --delete-key &amp;quot;User Name&amp;quot;&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Before we continue, let&amp;rsquo;s just consider a real-world scenario:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine at this point you&amp;rsquo;re not entirely sure if the public key you&amp;rsquo;ve been given over the internet is actually from who you were expecting it from (let&amp;rsquo;s call them &amp;ldquo;Bob&amp;rdquo;). Maybe there are some nefarious government types intercepting your communication and the public key you received is theirs and not Bob&amp;rsquo;s.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You would need to call or find &lt;em&gt;some form&lt;/em&gt; of secure communication channel with Bob (or someone who you trust to know bob) to verify the public key really does belong to Bob. But what do you check any way? You could read out the contents of the public key (e.g. &lt;code&gt;cat bobs-public.key&lt;/code&gt;) but this would be pain stakingly tedious.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another way would be to get Bob to give you the shortened &amp;lsquo;fingerprint&amp;rsquo; which is derived from his public key. You do that by running the following command and asking Bob if it matches what he&amp;rsquo;s seeing:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --fingerprint bob@example.org&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will return something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pub   4096R/DD86E7F5 2016-05-24 [expires: 2017-05-24]&#xA;      Key fingerprint = FDFB E9B5 24BA 6972 A3AA  44B9 A1B1 7E6F DD86 E7F5&#xA;uid                  Mark McDonnell (Personal) &amp;lt;mark.mcdx@gmail.com&amp;gt;&#xA;sub   4096R/A3FDEBC6 2016-05-24 [expires: 2017-05-24]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice the &lt;code&gt;Key fingerprint&lt;/code&gt; section &lt;code&gt;FDFB E9B5 24BA 6972 A3AA  44B9 A1B1 7E6F DD86 E7F5&lt;/code&gt;. That&amp;rsquo;s what I would read out to someone if they called me to say they wanted to verify the public key they had really did belong to me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, once you have the public key of your recipient you can encrypt a file using it, like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --encrypt -u &amp;quot;Sender User Name&amp;quot; -r &amp;quot;Receiver User Name&amp;quot; somefile&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;it can sometimes be better to use the &lt;code&gt;pub&lt;/code&gt; identifier number (especially when you have multiple keys with the same email). So if your pub id is &lt;code&gt;1234A/BC56D7E5&lt;/code&gt; then you&amp;rsquo;d use &lt;code&gt;-u BC56D7E5&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To decrypt a GPG encrypted file, the person sending you the encrypted file would have used your public key to encrypt the data. So the following command will locate your private key automatically (if you have multiple secret keys it&amp;rsquo;ll ask for the password):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg -d some_encrypted_file.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example, it&amp;rsquo;ll display the contents of the file in stdout; so you&amp;rsquo;ll need to redirect it to a file or alternatively use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg -o output_file -d some_encrypted_file.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;symmetrical-encryption&#34;&gt;Symmetrical encryption&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t want to encrypt a file using your own key pair, you can use standard symmetrical encryption:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --symmetric secrets.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll be asked to enter a passphrase to complete the encryption. Then if you want to decrypt the file you simply run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg secrets.txt.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;ll ask for the passphrase and then it&amp;rsquo;ll extract the file to the current directory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also modify the default cipher encryption algorithm, then use the &lt;code&gt;--cipher-algo&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --verbose --cipher-algo AES256 --symmetric secrets.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;use &lt;code&gt;--verbose&lt;/code&gt; without &lt;code&gt;--cipher-algo&lt;/code&gt; to see GPG&amp;rsquo;s default algorithm&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To see a list of available cipher algorithms, then execute the following command and look for the section &lt;code&gt;Cipher&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --version&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So for me this outputs:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg (GnuPG) 1.4.20&#xA;Copyright (C) 2015 Free Software Foundation, Inc.&#xA;License GPLv3+: GNU GPL version 3 or later &amp;lt;http://gnu.org/licenses/gpl.html&amp;gt;&#xA;This is free software: you are free to change and redistribute it.&#xA;There is NO WARRANTY, to the extent permitted by law.&#xA;&#xA;Home: ~/.gnupg&#xA;Supported algorithms:&#xA;Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA&#xA;Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,&#xA;        CAMELLIA128, CAMELLIA192, CAMELLIA256&#xA;Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224&#xA;Compression: Uncompressed, ZIP, ZLIB, BZIP2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;key-signing&#34;&gt;Key Signing&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;GPG let&amp;rsquo;s you &amp;ldquo;sign&amp;rdquo; a key, and which tells GPG you &lt;em&gt;trust&lt;/em&gt; this key you have been provided (i.e. you have verified it belongs to who you think it should belong to). To sign a key you&amp;rsquo;ve imported, simply run the following command and change the email to something relevant:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --sign-key bob@example.org&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The real purpose of this is that if someone else (Alice) sees you&amp;rsquo;ve &amp;lsquo;signed&amp;rsquo; another person&amp;rsquo;s key (Bob&amp;rsquo;s), then if Alice trusts you she is more likely to implicitly trust Bob as well. It&amp;rsquo;s a web of trust.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for Bob to benefit from your &amp;lsquo;trust&amp;rsquo; you need to send him back the key you&amp;rsquo;ve signed:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --export --armor bob@example.org&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will send their public key to &lt;code&gt;stdout&lt;/code&gt; along with your signature and so they can run the following command to import the signed data you&amp;rsquo;ve provided:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --import &amp;lt;file path&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;digital-signatures&#34;&gt;Digital Signatures&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Earlier, when discussing PKI, we mentioned the use of a MAC which was a form of &amp;lsquo;digital signature&amp;rsquo;. The benefit of a signature is to allow you to verify that the file (encrypted &lt;em&gt;or&lt;/em&gt; plaintext) was indeed created by the person you think it was.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In GPG there are three types of signatures:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;clearsigned&lt;/li&gt;&#xA;&lt;li&gt;detached&lt;/li&gt;&#xA;&lt;li&gt;attached signatures&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;For the purposes of this demonstration I should clarify that I have multiple GPG profiles on my laptop, but I&amp;rsquo;ll refer to two of them as &amp;ldquo;Bob&amp;rdquo; and &amp;ldquo;Alice&amp;rdquo;. The reason I&amp;rsquo;m mentioning this is that I&amp;rsquo;ll use Bob to sign stuff and I&amp;rsquo;ll use Alice for the verification of the signed data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to verify a signature you need to have the public key for the person who signed the data. Hence utilising multiple GPG profiles makes this easier to demonstrate. So let&amp;rsquo;s start by creating a secret file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo foobar &amp;gt; secret.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h5 id=&#34;clearsigned-signatures&#34;&gt;clearsigned signatures&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;OK, so let&amp;rsquo;s begin with Bob creating a clearsign signature:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --local-user Bob --clearsign secret.txt &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once we run this command we can see the file &lt;code&gt;secret.txt.asc&lt;/code&gt; was created:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ cat secret.txt.asc&#xA;-----BEGIN PGP SIGNED MESSAGE-----&#xA;Hash: SHA256&#xA;&#xA;foobar&#xA;-----BEGIN PGP SIGNATURE-----&#xA;Version: GnuPG v2&#xA;&#xA;iQIcBAEBCAAGBQJYIZjsAAoJEMtev7lWHIYbIWkP/jsqtpP7FzWzrS1r4ABgKjG3&#xA;QCME6XtISPo8IC2m0BZ57wJcE+zw86P7TigzwenwwNgcVsIMQi/u5TUA5IEp1sUa&#xA;IBLk5lMFVWhbJryhgWz+qTGUsnnhu9vZUBjJddNe//Jr2sXlJUPxw+dHnOFGtDpR&#xA;90nl+7/gf2+0IdsgX5FstIOfhZLeaeuI4O6NNlwn0GiZW4GirusGpfhP6xrPpYir&#xA;GoK5D5v2A0uKfsmWdFA+1wxrk0H5eVghLKN6Ffy2PHIlQaUSzMlexpwzbls0rLlO&#xA;UK445AlmZHIWWxc42iwCx9hjdtd+lTg4GXWz3r03iwp9L5pJkaqLFBDpLr3MSdm8&#xA;kyMqIevZ9AM3thtQ6T9NFmMVpMGcpjvacy6HxJ0r3eWsQNMXfKcZo1AtcKz0Icqw&#xA;tGaO07gcKBdkdwf2+XwTqm/x4LZZFyKsaXJReuQoEWd2+mJJLqgSy4cgfaBKX1e3&#xA;YF8ES6RSIeDmxcDaUx9exBkRsj1l0Ot7AYCRmCdYo+CYUBARag3OWswGNwPQ2TLd&#xA;c3DoNmbApzPG0V5VTbjarSWuiBCjcY5PfYDGkM2+IOaPL9LmZKDzeEGeaQiJ4k7a&#xA;lBqmqvAB6mQ2ZSHGywCUogbg9pwDV6UY93o10QRR8OapmXqW+H0FRkFsH/Sz1yff&#xA;J4rLy4J820CAFgUKaUfx&#xA;=KdyK&#xA;-----END PGP SIGNATURE-----&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alice can now verify the file was signed by Bob (as she has Bob&amp;rsquo;s public key already):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gpg --local-user Alice --verify secret.txt.asc &#xA;&#xA;gpg: Signature made Tue Nov  8 09:20:44 2016 GMT using RSA key ID 561C861B&#xA;gpg: Good signature from &amp;quot;Profile 1 (Bob) &amp;lt;example@integralist.co.uk&amp;gt;&amp;quot; [ultimate]&#xA;gpg: WARNING: not a detached signature; file &#39;secret.txt&#39; was NOT verified!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The downside to using a clearsign signature is three fold:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;it&amp;rsquo;s not encrypted data&lt;/li&gt;&#xA;&lt;li&gt;it&amp;rsquo;s not the original file&lt;/li&gt;&#xA;&lt;li&gt;it&amp;rsquo;s not compressed&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The first is obviously not great, but is OK if you don&amp;rsquo;t care about the message being visible and you&amp;rsquo;re only interested in proofing you signed it. The second item is a bigger problem in that you have modified the file to &lt;em&gt;include&lt;/em&gt; the signature. Meaning the file is no longer the same, and when signing data you shouldn&amp;rsquo;t modify the data in order to do the signing. The third item is equally not great depending on the size of the file and having to send a potentially large file over the network.&lt;/p&gt;&#xA;&#xA;&lt;h5 id=&#34;detached-signatures&#34;&gt;detached signatures&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at the second type of signature, a &amp;lsquo;detached signature&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --local-user Bob --detach-sign secret.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So once you run this command you&amp;rsquo;ll find a &lt;code&gt;secret.txt.sig&lt;/code&gt; file has been generated (the &lt;code&gt;secret.txt&lt;/code&gt; still hasn&amp;rsquo;t been encrypted). You can&amp;rsquo;t see the contents of the &lt;code&gt;.sig&lt;/code&gt; file as it has been compressed †&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;† this is not the same as being &amp;lsquo;encrypted&amp;rsquo;, it is just compressed for the sake of performance and easier transportation&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This is better than &lt;code&gt;--clearsign&lt;/code&gt; as the original file hasn&amp;rsquo;t been modified in order to produce the signature. But this does mean in order for Alice to verify the signature, she needs to have the original plaintext file. If she doesn&amp;rsquo;t, then you&amp;rsquo;ll have to send her both the signature and the file.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$ gpg --local-user Alice --verify secret.txt.sig&#xA;&#xA;gpg: assuming signed data in &#39;secret.txt&#39;&#xA;gpg: Signature made Tue Nov  8 09:26:56 2016 GMT using RSA key ID 561C861B&#xA;gpg: Good signature from &amp;quot;Profile 1 (Bob) &amp;lt;example@integralist.co.uk&amp;gt;&amp;quot; [ultimate]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h5 id=&#34;attached-signatures&#34;&gt;attached signatures&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;Finally, let&amp;rsquo;s consider &amp;lsquo;attached signatures&amp;rsquo;. This mechanism enforces the use of verification before you can use the file (hence why the signature is considered &lt;em&gt;attached&lt;/em&gt; to the file).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order for Bob to attach his signature (and thus making verification mandatory) he must use &lt;code&gt;--sign&lt;/code&gt;. The attachment aspect is sort of theorectical in that it works by explicitly specifying &lt;code&gt;--encrypt&lt;/code&gt;, and so if you didn&amp;rsquo;t use that flag then this example becomes much like &lt;code&gt;--clearsign&lt;/code&gt; but with the small benefit of being compressed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But if you do use &lt;code&gt;--encrypt&lt;/code&gt; with &lt;code&gt;--sign&lt;/code&gt; then Alice can&amp;rsquo;t just use &lt;code&gt;--verify&lt;/code&gt; by itself, she has to use &lt;code&gt;--decrypt&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --local-user Bob --encrypt --recipient Alice --sign secret.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, this generates a &lt;code&gt;secret.txt.gpg&lt;/code&gt; file, but this time Alice must enter the passphrase for &lt;em&gt;her&lt;/em&gt; private key in order to use the &lt;code&gt;--decrypt&lt;/code&gt; flag as the file is no longer just &amp;lsquo;compressed&amp;rsquo; it is also &amp;lsquo;encrypted&amp;rsquo; as well (&lt;code&gt;--decrypt&lt;/code&gt; doesn&amp;rsquo;t just decrypt the encrypted file but also &amp;lsquo;verifies&amp;rsquo; its attached signature):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --local-user Alice --decrypt secret.txt.gpg_private&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which results in the following ouput:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;foobar&#xA;gpg: Signature made Tue Nov  8 10:13:37 2016 GMT using RSA key ID 561C861B&#xA;gpg: Good signature from &amp;quot;Profile 1 (Bob) &amp;lt;example@integralist.co.uk&amp;gt;&amp;quot; [ultimate]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;All other uses of &lt;code&gt;--decrypt&lt;/code&gt; simply meant &lt;em&gt;decompress&lt;/em&gt; the file, hence no passphrase was required. This also explains why Bob had to explicitly specify &lt;code&gt;--recipient&lt;/code&gt; when using &lt;code&gt;--encrypt&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in all these examples I use &lt;code&gt;--local-user&lt;/code&gt; to change the GPG profile.&lt;br&gt;&#xA;But you could also use &lt;code&gt;--default-key&lt;/code&gt; if you wanted&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h4 id=&#34;revoking-keys&#34;&gt;Revoking Keys&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;ve pulled keys from a public server:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --keyserver pgp.mit.edu  --search-keys bob@example.org&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then you want to regularly check those keys are still valid, and haven&amp;rsquo;t been compromised:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg --refresh-keys&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can specify &lt;code&gt;--keyserver&lt;/code&gt; when refreshing key data&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;openssl-encryption&#34;&gt;OpenSSL encryption&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The easiest way to encrypt a file using OpenSSL is like so (the password for the file is &lt;code&gt;foobar&lt;/code&gt; and is specified at the end of the command; you&amp;rsquo;ll also see we&amp;rsquo;re using a &lt;a href=&#34;https://en.wikipedia.org/wiki/Salt_(cryptography)&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;-salt&lt;/code&gt;&lt;/a&gt; with the password to help improve the security):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo -n &#39;someTextIWantToEncrypt&#39; | openssl enc -e -salt -out test.txt -aes-256-cbc -pass pass:foobar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To decrypt this file we can use the &lt;code&gt;-d&lt;/code&gt; flag (instead of &lt;code&gt;-e&lt;/code&gt; which is for encryption):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl enc -d -salt -in test.txt -out decrypted.txt -aes-256-cbc -pass pass:foobar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively you can make things more complex, but ultimately more secure, by encrypting the file using the public key of the person you want to share the file with (which is how GPG works &amp;lsquo;out-of-the-box&amp;rsquo;). As this means the only person who can decrypt the file is the owner of the private key associated with the public key used for encryption.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the following example let&amp;rsquo;s assume you/we are &amp;ldquo;Alice&amp;rdquo; and the recipient of the encrypted file is &amp;ldquo;Bob&amp;rdquo;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Bob needs to send us their RSA key in the PEM certificate format&#xA;&#xA;# So first thing Bob does is generate a PEM containing his private key&#xA;openssl rsa -in id_rsa -outform pem &amp;gt; id_rsa.pem&#xA;&#xA;# Second thing Bob does is generate a PEM containing his public key&#xA;openssl rsa -in id_rsa -pubout -outform pem &amp;gt; id_rsa.pub.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point Alice and Bob have to figure out how to securely share Bobs public key with Alice. I would suggest they do this in person to avoid network sniffers getting involved and Alice encrypting the file with the wrong details (this is where PKI helps with &amp;ldquo;authentication&amp;rdquo; - we don&amp;rsquo;t have that process/mechanism here unfortunately).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once Alice has Bob&amp;rsquo;s public key she&amp;rsquo;ll follow these steps:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Alice generates a 256 bit (32 byte) random key&#xA;openssl rand -base64 32 &amp;gt; key.bin&#xA;&#xA;# Alice encrypts the random key using Bobs public key&#xA;openssl rsautl -encrypt -inkey id_rsa.pub.pem -pubin -in key.bin -out key.bin.enc&#xA;&#xA;# Alice encrypts the secret file using Bobs public key&#xA;openssl enc -aes-256-cbc -salt -in SECRET_FILE -out SECRET_FILE.enc -pass file:./key.bin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alice can now send the encrypted file (e.g. &lt;code&gt;SECRET_FILE.enc&lt;/code&gt;) to Bob. Once Bob has the encrypted file, he&amp;rsquo;ll follow these steps:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Bob decrypts the random key using his private key&#xA;openssl rsautl -decrypt -inkey id_rsa.pem -in key.bin.enc -out key.bin&#xA;&#xA;# Bob decrypts the file using his private key&#xA;openssl enc -d -aes-256-cbc -in SECRET_FILE.enc -out SECRET_FILE -pass file:./key.bin&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;keybase&#34;&gt;Keybase&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://keybase.io/&#34; target=&#34;_blank&#34;&gt;Keybase&lt;/a&gt; was mentioned earlier when we were discussing the problem of &amp;lsquo;authentication&amp;rsquo; and that there are many public repositories where you can locate a person&amp;rsquo;s public key. &lt;a href=&#34;https://keybase.io/&#34; target=&#34;_blank&#34;&gt;Keybase&lt;/a&gt; is a recent attempt at trying to solve this problem in a modern way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wont cover all the details of getting setup with Keybase (plus it&amp;rsquo;s invitation only at the moment), but in essence you need to download their command line tool:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;brew install keybase&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once you have that installed you can log into your account:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase login&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point you can use either the website or the command line tool to generate a keypair for your account. If using the command line, then execute the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase pgp gen&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Alternatively you might want to use an already existing private key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase pgp select&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the &lt;code&gt;keybase&lt;/code&gt; program will push the public key part of your PGP or GPG key pair to the Keybase website and associate it with your Keybase account&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The point of Keybase is to help you verify the person you want to communicate with is who they say they are. So Keybase let&amp;rsquo;s users prove who they are by authenticating with their social accounts. For example, if I search for a friend of mine on Keybase:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase search sthulb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then this will display the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sthulb twitter:sthulb github:sthulb dns://thulbourn.com&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now I know that he is &lt;code&gt;sthulb&lt;/code&gt; on GitHub so if the user &lt;code&gt;sthulb&lt;/code&gt; was able to verify the GitHub account of the same user to Keybase then I&amp;rsquo;m pretty sure this is a legit setup and that I&amp;rsquo;m OK to communicate with this Keybase user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if I wanted to encrypt a file for my friend, then I would do:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase encrypt -i secrets.txt -o secrets.txt.asc sthulb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will then display the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;▶ INFO Identifying recipient sthulb&#xA;✔ public key fingerprint: D38B 2537 67F4 1E59 DFE6 7879 EDD0 4A02 7DD5 BD7A&#xA;✔ admin of DNS zone thulbourn.com: found TXT entry keybase-site-verification=JVupJZY1EQbjTiYiLc6JSVNcOWACdBEq9WfuJJWT0qg&#xA;✔ &amp;quot;sthulb&amp;quot; on twitter: https://twitter.com/sthulb/status/692285366053834753&#xA;✔ &amp;quot;sthulb&amp;quot; on github: https://gist.github.com/13a7654d90750bf154c3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;.asc&lt;/code&gt; is a convention to indicate a file has been encrypted&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;My friend would then be able to decrypt the encrypted file I send to him with:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase decrypt -i secrets.txt.asc -o secrets.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But if someone sends you an encrypted file using your Keybase public key but is encrypted via a different tool, such as their own local GPG or PGP, then you&amp;rsquo;d decrypt the file with (for example):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase pgp decrypt -i some_encrypted_file.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to encrypt a file for someone who doesn&amp;rsquo;t use Keybase (e.g. they use their own local GPG installation), then you can export your public/private key from Keybase using the command line tool and then import them into your local GPG so you can utilise GPG to encrypt your data and specify the user&amp;rsquo;s public key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;keybase pgp export -o keybase.public.key&#xA;keybase pgp export -s -o keybase.private.key&#xA;gpg --import keybase.public.key&#xA;gpg --allow-secret-key-import --import keybase.private.key&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice the use of &lt;code&gt;-s&lt;/code&gt; to export the private key&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now you can encrypt data via GPG using your Keybase private key:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo foobar &amp;gt; secret.txt&#xA;gpg --encrypt -u 123 -r 456 secret.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;123&lt;/code&gt; being your keybase identifier inside GPG and&lt;br&gt;&#xA;&lt;code&gt;456&lt;/code&gt; being the recipient identifier&lt;br&gt;&#xA;(assuming you&amp;rsquo;ve imported their public key already)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The recipient can now decrypt the file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;gpg -d secret.txt.gpg&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;which-should-i-use&#34;&gt;Which &lt;em&gt;should&lt;/em&gt; I use?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OpenSSL is not considered secure enough in today&amp;rsquo;s digital age. There are known bugs with the implementation of the OpenSSL &lt;code&gt;enc&lt;/code&gt; command, and so the recommendation in the security community seems to be to ditch OpenSSL for GPG (at least for these types of scenarios where we&amp;rsquo;re simply encrypting a file that we want to share with someone else).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;creating-self-signing-issuing-and-revoking-certificates&#34;&gt;Creating, self-signing, issuing and revoking certificates&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so I &lt;em&gt;was&lt;/em&gt; going to go through the process of creating a new CA root and then self-signing the certificate so we can then go ahead and issue certificates from our own personal CA. The idea was to indicate how you might do this for an organisation that doesn&amp;rsquo;t want to pay for a CA to provide them a certificate (e.g. services that only allow access via client certificates doesn&amp;rsquo;t have to worry about being trusted; as long the employees have trusted the organisation&amp;rsquo;s self-signed certificate then it&amp;rsquo;s fine).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I&amp;rsquo;m not going to do that is because Ivan Ristić (author of &amp;ldquo;Bulletproof SSL and TLS&amp;rdquo;) has already done the leg work and has made it freely available in his ebook &amp;ldquo;OpenSSL Cookbook&amp;rdquo;. Which you can get here &lt;a href=&#34;https://www.feistyduck.com/books/openssl-cookbook/&#34; target=&#34;_blank&#34;&gt;https://www.feistyduck.com/books/openssl-cookbook/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although, if you want a super quick run down&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can generate a CSR (Certificate Signing Request; which you send to a CA to approve) using&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl req -sha256 -new -key my-private-key.pem -out csr.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can then self-sign that certificate (while you wait for the CA to officially create you a cert and sign it) using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;openssl x509 -req -days 365 -in csr.pem -signkey my-private-key.pem -out my-certificate.pem&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;create key pair + cert in a one liner&lt;br&gt;&#xA;&lt;code&gt;openssl req -nodes -new -x509 -keyout server.key -out server.cert&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;update&#34;&gt;UPDATE&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;OK so I ended up writing about this any way &lt;a href=&#34;/posts/client-cert-authentication/&#34;&gt;in this article&lt;/a&gt; where I discuss how to handle Client Certificate Authentication using Docker.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Hopefully, you&amp;rsquo;ve stuck with me until the end here and that you found the information contained useful, or dare say even enlightening. I wrote this post to help solidify my own knowledge and for this to become a future reference point for myself; but I ended up really enjoying diving into aspects such as the PKI and SSL handshake process, as it&amp;rsquo;s an area that has confused me for the longest time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If there are any glaring mistakes (I&amp;rsquo;m sure there will be a few) then do please let me know so I can update and correct.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;references&#34;&gt;References&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://technet.microsoft.com/en-us/library/cc785811(v=ws.10).aspx&#34; target=&#34;_blank&#34;&gt;technet.microsoft.com&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://devcentral.f5.com/articles/ssl-profiles-part-1&#34; target=&#34;_blank&#34;&gt;devcentral.f5.com&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html&#34; target=&#34;_blank&#34;&gt;AWS ELB SSL Cert upload&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/security-basics/</guid>
      <link>https://www.integralist.co.uk/posts/security-basics/</link>
      <pubDate>Tue, 25 Aug 2015 00:00:00 +0000</pubDate>
      <title>Security basics with GPG, OpenSSH, OpenSSL and Keybase</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I wanted to learn about how to use the popular proxy server &lt;a href=&#34;http://nginx.org&#34; target=&#34;_blank&#34;&gt;nginx&lt;/a&gt; for handling &amp;ldquo;reverse proxy&amp;rdquo; duties on a Ruby project I was working on. So I decided the easiest thing to do in order to play around with nginx (as I work on a MacBook Pro laptop), would be to install and run it (and my back-end application) within &lt;a href=&#34;http://docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt; containers.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I did some preliminary Googling and sadly didn&amp;rsquo;t find anything straightforward that demonstrated this relatively simple requirement (i.e. run nginx and have it proxy requests to a back-end service). So I decided it would be best to write about it myself&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now if you&amp;rsquo;re unsure of what a reverse proxy does, it simply takes &lt;em&gt;in&lt;/em&gt; traffic (i.e. users requesting a website domain) and proxies those requests onto another service (the service could be external to the host server or it could be running on the same box - which is the scenario I have - and typically the service being proxied to isn&amp;rsquo;t publically available to the internet).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The nginx server has many features, such as load balancing, caching and serving static files (to name but a few). When used as a reverse proxy it can also be useful for handling SSL termination (i.e. SSL is an expensive operation and so the proxy server will authenticate the provided credentials - allowing access - but terminate the SSL requirement at that point before directing traffic onto the other protected service).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this post we&amp;rsquo;ll be primarily focusing on using nginx as a reverse proxy, although I also demonstrate how to serve static files. But the focus will be reverse proxying and not demonstrating other features within nginx. I&amp;rsquo;ll also not be explaining Docker and how it works (I&amp;rsquo;m assuming you&amp;rsquo;ve used Docker in some form or another previously).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lastly, I&amp;rsquo;m going to take you on the same journey I took while setting this all up; so rather than work through a perfect scenario you&amp;rsquo;ll get to see some of the errors I stumbled across along the way. If you&amp;rsquo;d prefer to just read the (small amount of) code then the next section is for you.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;just-give-me-the-code&#34;&gt;Just give me the code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Integralist/Docker-Examples/tree/master/Nginx&#34; target=&#34;_blank&#34;&gt;github.com/integralist/docker-examples/nginx&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;setting-up-nginx&#34;&gt;Setting up nginx&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So to begin with, I went to &lt;a href=&#34;https://hub.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker Hub&lt;/a&gt; and found the &lt;a href=&#34;https://registry.hub.docker.com/_/nginx/&#34; target=&#34;_blank&#34;&gt;official nginx Docker image&lt;/a&gt;. It suggested the easiest thing to do to get started was to download and run the image; so knowing not a lot about nginx, that&amp;rsquo;s exactly what I did:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name nginx-container -P -d nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you can use the &lt;code&gt;-p &amp;lt;host_port&amp;gt;:&amp;lt;container_port&amp;gt;&lt;/code&gt; option instead of &lt;code&gt;-P&lt;/code&gt; if you&amp;rsquo;re not going to be running multiple nginx instances (again, for the moment I was just following the recommendation from Docker Hub)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once the container was running I attempted to &lt;code&gt;curl&lt;/code&gt; the endpoint (something like &lt;code&gt;http://localhost:&amp;lt;port_number_container_mapped_to&amp;gt;&lt;/code&gt;) but I found this didn&amp;rsquo;t work; and by that I mean it didn&amp;rsquo;t return a recognisable nginx home page as was suggested it would. This was the first trip-up I made.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason this didn&amp;rsquo;t work is because (for me) using &lt;a href=&#34;http://boot2docker.io/&#34; target=&#34;_blank&#34;&gt;Boot2Docker&lt;/a&gt; on a Mac - rather than being on a pure Linux machine capable of running Docker natively - means that localhost is the Mac and not the Docker host (which is the Boot2Docker VM). So to resolve that issue I needed to curl the ip of the Boot2Docker host. To get the ip simply run &lt;code&gt;boot2docker ip&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So your curl command (depending on what OS you&amp;rsquo;re running on) should look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(&amp;lt;docker_host_ip&amp;gt;:&amp;lt;port_number_container_mapped_to&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For me this was:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):32781&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Executing this resulted in the following output:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;&#xA;&amp;lt;style&amp;gt;&#xA;    body {&#xA;        width: 35em;&#xA;        margin: 0 auto;&#xA;        font-family: Tahoma, Verdana, Arial, sans-serif;&#xA;    }&#xA;&amp;lt;/style&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and&#xA;working. Further configuration is required.&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;p&amp;gt;For online documentation and support please refer to&#xA;&amp;lt;a href=&amp;quot;http://nginx.org/&amp;quot;&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;&#xA;Commercial support is available at&#xA;&amp;lt;a href=&amp;quot;http://nginx.com/&amp;quot;&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&#xA;&#xA;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you for using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;mounting-our-own-static-files&#34;&gt;Mounting our own static files&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now at this point having a standard nginx welcome page isn&amp;rsquo;t very useful. We want to add our own nginx configuration and to have it serve up our own static files. To achieve that with Docker we&amp;rsquo;ll need to use &lt;a href=&#34;https://docs.docker.com/userguide/dockervolumes/&#34; target=&#34;_blank&#34;&gt;Volumes&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But before I show the command for that, I need to show you the project directory I have right now:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── Dockerfile&#xA;├── Gemfile&#xA;├── Gemfile.lock&#xA;├── app.rb&#xA;├── nginx.conf&#xA;└── html&#xA;    └── test.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t the final directory structure mind you, but it&amp;rsquo;s what I initially started out with. You&amp;rsquo;ll see as we move on I had to add a little more structure to the project. But for now, this is what we&amp;rsquo;ve got.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ll show the contents of these files now, most of them are really small anyway:&lt;/p&gt;&#xA;&#xA;&lt;h4 id=&#34;dockerfile&#34;&gt;Dockerfile&lt;/h4&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM ruby:2.1-onbuild&#xA;CMD [&amp;quot;ruby&amp;quot;, &amp;quot;app.rb&amp;quot;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;gemfile&#34;&gt;Gemfile&lt;/h4&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;source &amp;quot;http://rubygems.org/&amp;quot;&#xA;&#xA;gem &amp;quot;sinatra&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;app-rb&#34;&gt;app.rb&lt;/h4&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;require &amp;quot;sinatra&amp;quot;&#xA;&#xA;set :bind, &amp;quot;0.0.0.0&amp;quot;&#xA;&#xA;get &amp;quot;/&amp;quot; do&#xA;  &amp;quot;Hello World&amp;quot;&#xA;end&#xA;&#xA;get &amp;quot;/foo&amp;quot; do&#xA;  &amp;quot;Foo!&amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;nginx-conf&#34;&gt;nginx.conf&lt;/h4&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;user nobody nogroup;&#xA;worker_processes auto;          # auto-detect number of logical CPU cores&#xA;&#xA;events {&#xA;  worker_connections 512;       # set the max number of simultaneous connections (per worker process)&#xA;}&#xA;&#xA;http {&#xA;  server {&#xA;    listen *:80;                # Listen for incoming connections from any interface on port 80&#xA;    server_name &amp;quot;&amp;quot;;             # Don&#39;t worry if &amp;quot;Host&amp;quot; HTTP Header is empty or not set&#xA;    root /usr/share/nginx/html; # serve static files from here&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;html-test-html&#34;&gt;html/test.html&lt;/h4&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hey there!&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;Here is my test HTML file&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;mounting-the-files&#34;&gt;Mounting the files&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see the syntax structure of the command I was looking to run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name nginx-container \&#xA;  -v /path/to/static/files/on/host:/usr/share/nginx/html:ro \&#xA;  -v /path/to/conf/on/host:/etc/nginx/nginx.conf:ro \&#xA;  -P -d nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example, you can see I&amp;rsquo;m using the &lt;code&gt;-v&lt;/code&gt; flag to mount my static files directory to &lt;code&gt;/usr/share/nginx/html&lt;/code&gt; as well as mounting my own nginx configuration file into the container at &lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;:ro&lt;/code&gt; sets the volumes to be &amp;ldquo;read only&amp;rdquo;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So for me, a working example looked like the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name nginx-container \&#xA;  -v $(pwd)/html:/usr/share/nginx/html:ro \&#xA;  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \&#xA;  -P -d nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the host path has to be absolute, so tweak it as necessary (I used &lt;code&gt;pwd&lt;/code&gt; to make the command shorter)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you want to debug things, then you can run the container not as a daemon (&lt;code&gt;-d&lt;/code&gt;) but with an interactive tty (&lt;code&gt;-it&lt;/code&gt;) and drop yourself inside of a bash shell:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run -it --name nginx-container \&#xA;  -v $(pwd)/html:/usr/share/nginx/html:ro \&#xA;  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \&#xA;  -P nginx bash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once the container is running and the &lt;code&gt;nginx.conf&lt;/code&gt; and static files are mounted as a Volume, you can verify that nginx is serving the static files by trying to hit localhost on port &lt;code&gt;80&lt;/code&gt; (as mentioned earlier: if you&amp;rsquo;re on a Mac using Boot2Docker like me, then you&amp;rsquo;ll need to access localhost via the Boot2Docker VM ip address instead):&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;don&amp;rsquo;t forget the port number I&amp;rsquo;ve used will be different for you (get yours from &lt;code&gt;docker ps&lt;/code&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):32781&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This will display a &lt;code&gt;403&lt;/code&gt; error page, which is to be expected because we&amp;rsquo;ve not mounted a folder that has a &lt;code&gt;index.html&lt;/code&gt; file. Our mounted directory only contained a &lt;code&gt;test.html&lt;/code&gt; file, so if we try to access that instead, then we&amp;rsquo;ll see it&amp;rsquo;ll be loaded without a problem:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):32781/test.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you were following along at home then you would have noticed that this returns the following HTML content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hey there!&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;Here is my test HTML file&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we try the exact same command again, but this time add the &lt;code&gt;-I&lt;/code&gt; flag (e.g. &lt;code&gt;curl -I &amp;lt;url&amp;gt;&lt;/code&gt; - this returns just the HTTP headers), we&amp;rsquo;ll see that this is indeed being served by nginx:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK&#xA;Server: nginx/1.9.3&#xA;Date: Sat, 01 Aug 2015 17:27:01 GMT&#xA;Content-Type: text/html&#xA;Content-Length: 53&#xA;Last-Modified: Sat, 01 Aug 2015 14:05:59 GMT&#xA;Connection: keep-alive&#xA;ETag: &amp;quot;55bcd247-35&amp;quot;&#xA;Accept-Ranges: bytes&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h4 id=&#34;dynamically-updating-containers-without-restart&#34;&gt;Dynamically updating containers without restart&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Because we&amp;rsquo;ve mounted the &lt;code&gt;html&lt;/code&gt; directory as a volume, we can now create an &lt;code&gt;index.html&lt;/code&gt; file for nginx to use as the root page to load when you request &lt;code&gt;http://$(boot2docker ip):32781/&lt;/code&gt;; and in doing this it&amp;rsquo;ll take effect immediately without requiring us to restart the container. Once we&amp;rsquo;ve created the file inside the &lt;code&gt;html&lt;/code&gt; directory, we can then make the relevant curl request to see nginx serve up the html file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Just so you know, the &lt;code&gt;index.html&lt;/code&gt; file I created looks like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;This is my home page&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;setting-up-the-ruby-application&#34;&gt;Setting up the Ruby application&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The Ruby application we&amp;rsquo;ll be creating is a super simple &lt;a href=&#34;http://sinatrarb.com/&#34; target=&#34;_blank&#34;&gt;Sinatra&lt;/a&gt; web application with two routes defined:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;code&gt;/&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;One of the first things you need to do is to make sure you run &lt;code&gt;bundle install&lt;/code&gt; so you have a &lt;code&gt;Gemfile.lock&lt;/code&gt; generated, otherwise the base Ruby image will complain. The reason it complains is because the base Docker image is using an &lt;code&gt;onbuild&lt;/code&gt; version of the Ruby image, and what this means is that it follows a &amp;ldquo;convention over configuration&amp;rdquo; model where by it assumes you have three files available (&lt;code&gt;app.rb&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt; and &lt;code&gt;Gemfile.lock&lt;/code&gt;) for it to automatically copy into the built Docker image for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you&amp;rsquo;ve done that, you can now build the Docker image:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t my-ruby-app .&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once the image is built, you can run your Ruby application like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name ruby-app -p 4567:4567 -d my-ruby-app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll notice we&amp;rsquo;re not using a dynamic port range because the Sinatra app we&amp;rsquo;ve created explicitly binds to port &lt;code&gt;4567&lt;/code&gt; and so I&amp;rsquo;m exposing that specific port to the Boot2Docker VM. We can then access this application directly with the following curl command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):4567/&#xA;&#xA;# Results in...&#xA;&#xA;Hello World%&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if we want to see the HTTP Headers coming back:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl -I http://$(boot2docker ip):4567/&#xA;&#xA;# Results in...&#xA;&#xA;HTTP/1.1 200 OK&#xA;Content-Type: text/html;charset=utf-8&#xA;Content-Length: 11&#xA;X-Xss-Protection: 1; mode=block&#xA;X-Content-Type-Options: nosniff&#xA;X-Frame-Options: SAMEORIGIN&#xA;Server: WEBrick/1.3.1 (Ruby/2.1.6/2015-04-13)&#xA;Date: Sun, 02 Aug 2015 09:20:47 GMT&#xA;Connection: Keep-Alive&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;linking-your-app-to-nginx&#34;&gt;Linking your app to nginx&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so we&amp;rsquo;re nearing the finish line now. We&amp;rsquo;ve got a working nginx container and a working Ruby container. We need to gel them together by making a request and having nginx proxy the request on to the Ruby container (if the request was aimed at that) or have nginx serve a static file if the request was relevant to that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To get this to work with Docker, we have two options:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Host file&lt;/li&gt;&#xA;&lt;li&gt;ENV variables&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Both options require a custom Dockerfile to be used for setting up nginx and both have about the same amount of complexity in different ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But to understand these options, we need to be sure we understand what Docker does when linking containers. So to clarify, when linking a container (Ruby) with another container (nginx), Docker adds the ip of the linked container (Ruby) into the other container (nginx). It does this by updating the container&amp;rsquo;s &lt;code&gt;/etc/hosts&lt;/code&gt; file with a new entry that looks something like the following (note the last line of the file output):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;host.conf  hostname   hosts&#xA;root@a4a3bde52f8e:/# cat /etc/hosts&#xA;172.17.0.19     a4a3bde52f8e&#xA;127.0.0.1       localhost&#xA;::1     localhost ip6-localhost ip6-loopback&#xA;fe00::0 ip6-localnet&#xA;ff00::0 ip6-mcastprefix&#xA;ff02::1 ip6-allnodes&#xA;ff02::2 ip6-allrouters&#xA;172.17.0.18     app 3435f6926e83 ruby-app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can test this yourself by using the following command, which interactively jumps into a running version of the nginx container:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --rm -it \&#xA;  --name nginx-container \&#xA;  --link ruby-app:app \&#xA;  -P nginx bash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Once inside the container, run &lt;code&gt;cat /etc/hosts&lt;/code&gt; to get the above output (or something similar to it at least - your ip will likely be different to mine).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;While you&amp;rsquo;re still inside the temporarily running nginx container, we can clarify the second option which is the ENV variable setup Docker handles. When linking a container, Docker will add details of the linked container as environment variables (as well as adding a new entry to the &lt;code&gt;/etc/hosts&lt;/code&gt; file). So while you&amp;rsquo;re still inside the running nginx container, execute the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;env | grep APP | sort&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we&amp;rsquo;re &lt;code&gt;grep&lt;/code&gt;ing for the phrase &lt;code&gt;APP&lt;/code&gt; as that&amp;rsquo;s what we specified in our &lt;code&gt;docker run&lt;/code&gt; command (i.e. &lt;code&gt;--link ruby-app:app&lt;/code&gt;)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;We should now see the following output (or something very similar):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;APP_ENV_BUNDLER_VERSION=1.10.6&#xA;APP_ENV_BUNDLE_APP_CONFIG=/usr/local/bundle&#xA;APP_ENV_GEM_HOME=/usr/local/bundle&#xA;APP_ENV_RUBY_DOWNLOAD_SHA256=1e1362ae7427c91fa53dc9c05aee4ee200e2d7d8970a891c5bd76bee28d28be4&#xA;APP_ENV_RUBY_MAJOR=2.1&#xA;APP_ENV_RUBY_VERSION=2.1.6&#xA;APP_NAME=/nginx-container/app&#xA;APP_PORT=tcp://172.17.0.18:4567&#xA;APP_PORT_4567_TCP=tcp://172.17.0.18:4567&#xA;APP_PORT_4567_TCP_ADDR=172.17.0.18&#xA;APP_PORT_4567_TCP_PORT=4567&#xA;APP_PORT_4567_TCP_PROTO=tcp&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice that Docker has capitalised the link name (e.g. &lt;code&gt;app&lt;/code&gt; is now &lt;code&gt;APP&lt;/code&gt;) and has used the convention of &lt;code&gt;&amp;lt;LINK_NAME&amp;gt;_&amp;lt;ENV_VAR_FROM_LINKED_CONTAINER&amp;gt;&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;choosing-an-option&#34;&gt;Choosing an option?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;With this knowledge secured in our minds, we can now understand what we need to do for each option (i.e. host file vs environment variable). For the host file option we can manipulate our &lt;code&gt;nginx.conf&lt;/code&gt; file manually (before building the image) to use a named &lt;code&gt;upstream&lt;/code&gt; server that references the &lt;code&gt;--link&lt;/code&gt; name we provided, as part of the &lt;code&gt;docker run&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whereas with the environment variables option we would need to manipulate the &lt;code&gt;nginx.conf&lt;/code&gt; file &lt;em&gt;dynamically&lt;/em&gt; at run time. So within our &lt;code&gt;Dockerfile&lt;/code&gt; we would add a shell script, which would be executed by the &lt;code&gt;CMD&lt;/code&gt; statement within the &lt;code&gt;Dockerfile&lt;/code&gt;. This shell script would run and use something like the &lt;code&gt;sed&lt;/code&gt; command to replace a placeholder reference within our &lt;code&gt;nginx.conf&lt;/code&gt; file (likely we&amp;rsquo;d use the &lt;code&gt;APP_PORT&lt;/code&gt; environment variable and do some regular expression parsing for the ip address). Once the placeholder had been replaced with the appropriate container ip, we would manually start nginx using &lt;code&gt;service nginx start&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Out of the two options, I think I&amp;rsquo;ll go with the &amp;ldquo;host file&amp;rdquo; one. So let&amp;rsquo;s run through the steps&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Create a new directory structure that looks like the following (you can grab the exact files from &lt;a href=&#34;https://github.com/Integralist/Docker-Examples/tree/master/Nginx&#34; target=&#34;_blank&#34;&gt;github.com/integralist/docker-examples/nginx&lt;/a&gt;):&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── docker-app&#xA;│   ├── Dockerfile&#xA;│   ├── Gemfile&#xA;│   ├── Gemfile.lock&#xA;│   └── app.rb&#xA;├── docker-nginx&#xA;│   ├── Dockerfile&#xA;│   └── nginx.conf&#xA;└── html&#xA;    ├── index.html&#xA;    └── test.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Build the images (we&amp;rsquo;ll see what these look like in a moment) for the Ruby app and nginx&lt;/li&gt;&#xA;&lt;li&gt;Run the Ruby app container&lt;/li&gt;&#xA;&lt;li&gt;Run the nginx container and link it to the running Ruby container&lt;/li&gt;&#xA;&lt;li&gt;Verify everything works&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Other than moving existing files (related to the building of the Ruby Docker image) inside of a &lt;code&gt;docker-app&lt;/code&gt; folder, the two biggest changes are the addition of a new &lt;code&gt;Dockerfile&lt;/code&gt; inside the &lt;code&gt;docker-nginx&lt;/code&gt; folder and the following updated &lt;code&gt;nginx.conf&lt;/code&gt; file:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;user nobody nogroup;&#xA;worker_processes auto;          # auto-detect number of logical CPU cores&#xA;&#xA;events {&#xA;  worker_connections 512;       # set the max number of simultaneous connections (per worker process)&#xA;}&#xA;&#xA;http {&#xA;  upstream app {&#xA;    server app:4567;            # app is automatically defined inside /etc/hosts by Docker&#xA;  }&#xA;&#xA;  server {&#xA;    listen *:80;                # Listen for incoming connections from any interface on port 80&#xA;    server_name &amp;quot;&amp;quot;;             # Don&#39;t worry if &amp;quot;Host&amp;quot; HTTP Header is empty or not set&#xA;    root /usr/share/nginx/html; # serve static files from here&#xA;&#xA;    location /app/ {            # catch any requests that start with /app/&#xA;      proxy_pass http://app;    # proxy requests onto our app server (i.e. a different container)&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The aim of the new configuration is to accept any requests to &lt;code&gt;/app/&lt;/code&gt; and proxy them onto our application server. So if we were to request &lt;code&gt;/app/&lt;/code&gt; we&amp;rsquo;d want nginx to proxy it to the Sinatra &lt;code&gt;/&lt;/code&gt; route; and if we were to request &lt;code&gt;/app/foo&lt;/code&gt; then we&amp;rsquo;d expect nginx to proxy it to the Sinatra &lt;code&gt;/foo&lt;/code&gt; route.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The new &lt;code&gt;Dockerfile&lt;/code&gt; we&amp;rsquo;ve created inside the &lt;code&gt;docker-nginx&lt;/code&gt; folder will have the following content:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;FROM ubuntu&#xA;&#xA;# install nginx&#xA;RUN apt-get update &amp;amp;&amp;amp; apt-get install -y nginx&#xA;RUN rm -rf /etc/nginx/sites-enabled/default&#xA;&#xA;# forward request and error logs to docker log collector&#xA;RUN ln -sf /dev/stdout /var/log/nginx/access.log&#xA;RUN ln -sf /dev/stderr /var/log/nginx/error.log&#xA;&#xA;EXPOSE 80 443&#xA;CMD [&amp;quot;nginx&amp;quot;, &amp;quot;-g&amp;quot;, &amp;quot;daemon off;&amp;quot;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;some bright chap by the name of &lt;a href=&#34;https://twitter.com/stevenjack85&#34; target=&#34;_blank&#34;&gt;Steven Jack&lt;/a&gt; suggested setting &lt;code&gt;ENTRYPOINT&lt;/code&gt; in the Dockerfile to &lt;code&gt;nginx&lt;/code&gt; and have the two options (&lt;code&gt;-g&lt;/code&gt; and &lt;code&gt;daemon off&lt;/code&gt;) left in the &lt;code&gt;CMD&lt;/code&gt;. Doing this means if you wanted to pass other options to nginx you wouldn&amp;rsquo;t have to duplicate all of your CMD&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So from the root of our project directory, let&amp;rsquo;s complete the next step and build our new Docker images (technically you don&amp;rsquo;t have to rebuild the Ruby application as there has been no changes to the &lt;code&gt;Dockerfile&lt;/code&gt;, but just for completion I&amp;rsquo;ll demonstrate the build command again).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First let&amp;rsquo;s rebuild the Ruby Docker image:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t my-ruby-app ./docker-app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s build our new custom nginx Docker image:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t my-nginx ./docker-nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The third step in our list was to run the Ruby container:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name ruby-app -p 4567:4567 -d my-ruby-app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s also verify that it&amp;rsquo;s running (the following command should return back &amp;ldquo;Hello World&amp;rdquo;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):4567/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now onto our fourth step, which was to run our custom nginx container whilst linking it to our already running ruby container:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker run --name nginx-container \&#xA;  -v $(pwd)/html:/usr/share/nginx/html:ro \&#xA;  -v $(pwd)/docker-nginx/nginx.conf:/etc/nginx/nginx.conf:ro \&#xA;  --link ruby-app:app \&#xA;  -P -d my-nginx&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The final step is to verify that everything worked as expected (i.e. we should be able to make a request to our Boot2Docker VM&amp;rsquo;s localhost and have it proxy the request through to our Ruby application server). But let&amp;rsquo;s do it in stages, so the first stage is to hit the root of localhost:&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the following example you&amp;rsquo;ll need to get the dynamically allocated port number for the nginx container. You can do this by running &lt;code&gt;docker ps&lt;/code&gt; and extracting the port number from the output provided&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):&amp;lt;dynamic_port_number&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This &lt;code&gt;curl&lt;/code&gt; request will result in the following output to stdout&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;This is my home page&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The second stage is to hit the &lt;code&gt;/test.html&lt;/code&gt; endpoint for localhost and make sure nginx is still serving back our static files correctly:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):&amp;lt;dynamic_port_number&amp;gt;/test.html&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This &lt;code&gt;curl&lt;/code&gt; request will result in the following output to stdout&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hey there!&amp;lt;/h1&amp;gt;&#xA;&amp;lt;p&amp;gt;Here is my test HTML file&amp;lt;/p&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Looking good. OK the third and final stage is to now try to hit the &lt;code&gt;/app/&lt;/code&gt; endpoint for localhost and make sure nginx is proxying the request through to our Ruby backend application server (and also sending the result back again!):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):32785/app/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This &lt;code&gt;curl&lt;/code&gt; request will result in the following output to stdout&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&#xA;  &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&#xA;  body { text-align:center;font-family:helvetica,arial;font-size:22px;&#xA;    color:#888;margin:20px}&#xA;  #c {margin:0 auto;width:500px;text-align:left}&#xA;  &amp;lt;/style&amp;gt;&#xA;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body&amp;gt;&#xA;  &amp;lt;h2&amp;gt;Sinatra doesn&amp;amp;rsquo;t know this ditty.&amp;lt;/h2&amp;gt;&#xA;  &amp;lt;img src=&#39;http://app/__sinatra__/404.png&#39;&amp;gt;&#xA;  &amp;lt;div id=&amp;quot;c&amp;quot;&amp;gt;&#xA;    Try this:&#xA;    &amp;lt;pre&amp;gt;get &amp;amp;#x27;&amp;amp;#x2F;app&amp;amp;#x2F;&amp;amp;#x27; do&#xA;  &amp;amp;quot;Hello World&amp;amp;quot;&#xA;end&#xA;&amp;lt;/pre&amp;gt;&#xA;  &amp;lt;/div&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Ewww? OK so we can see nginx &lt;em&gt;is&lt;/em&gt; proxying through to our Ruby application server, but the server doesn&amp;rsquo;t seem to know how to handle the request &lt;code&gt;/app/&lt;/code&gt;? Maybe it&amp;rsquo;s something to do with the extra forward slash on the end of the request? If I change it to &lt;code&gt;/app&lt;/code&gt; instead we&amp;rsquo;ll see what that does:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;curl http://$(boot2docker ip):32785/app&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This &lt;code&gt;curl&lt;/code&gt; request will result in the following output to stdout&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;&#xA;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;301 Moved Permanently&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&#xA;&amp;lt;body bgcolor=&amp;quot;white&amp;quot;&amp;gt;&#xA;&amp;lt;center&amp;gt;&amp;lt;h1&amp;gt;301 Moved Permanently&amp;lt;/h1&amp;gt;&amp;lt;/center&amp;gt;&#xA;&amp;lt;hr&amp;gt;&amp;lt;center&amp;gt;nginx/1.4.6 (Ubuntu)&amp;lt;/center&amp;gt;&#xA;&amp;lt;/body&amp;gt;&#xA;&amp;lt;/html&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Hmm, ok that&amp;rsquo;s not much better. So what&amp;rsquo;s going on here? Well, we&amp;rsquo;re seeing the &lt;code&gt;301&lt;/code&gt; redirect because Sinatra is redirecting anything without a forward slash. So ok, but what about the &amp;ldquo;Sinatra doesn&amp;rsquo;t know this ditty&amp;rdquo; error?&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;the-final-solution&#34;&gt;The final solution&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The cause of the problem is because we&amp;rsquo;ve misconfigured nginx. The solution to the issue requires us to know a &lt;em&gt;very&lt;/em&gt; subtle detail about how nginx location blocks work, which is:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t put a forward slash &lt;code&gt;/&lt;/code&gt; at the end of the upstream name, then you&amp;rsquo;ll find nginx passes the request exactly as it was made (i.e. &lt;code&gt;/app/&lt;/code&gt;) through to the backend service, as apposed to passing it as just &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, we had set the proxy to pass to &lt;code&gt;http://app;&lt;/code&gt; which meant a request to &lt;code&gt;/app/&lt;/code&gt; was being passed to Sinatra as &lt;code&gt;/app/&lt;/code&gt; and a request to &lt;code&gt;/app/foo&lt;/code&gt; was being passed on to Sinatra as &lt;code&gt;/app/foo&lt;/code&gt;; and as you can see from the Sinatra application code, we have no such routes defined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What we should do instead is change the proxy pass value to &lt;code&gt;http://app/;&lt;/code&gt; (notice the extra forward slash just before the closing semi-colon).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By putting a &lt;code&gt;/&lt;/code&gt; after the upstream name means it acts more like nginx&amp;rsquo;s &lt;code&gt;alias&lt;/code&gt; directive which remaps requests for you. If I kept it as &lt;code&gt;http://app;&lt;/code&gt;, then I would&amp;rsquo;ve needed to have added an &lt;code&gt;/app/&lt;/code&gt; route to my Ruby application. But the additional forward slash remaps &lt;code&gt;/app/&lt;/code&gt; so it&amp;rsquo;s passed to Sinatra as &lt;code&gt;/&lt;/code&gt; (we have a route for that) as well as remapping &lt;code&gt;/app/foo&lt;/code&gt; to just &lt;code&gt;/foo&lt;/code&gt; (we have a route for that too!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So with this in mind you&amp;rsquo;ll see in GitHub I&amp;rsquo;ve updated the &lt;code&gt;nginx.conf&lt;/code&gt; to look like the following (with additional comments to clarify the behaviour):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;user nobody nogroup;&#xA;worker_processes auto;          # auto-detect number of logical CPU cores&#xA;&#xA;events {&#xA;  worker_connections 512;       # set the max number of simultaneous connections (per worker process)&#xA;}&#xA;&#xA;http {&#xA;  upstream app {&#xA;    server app:4567;            # app is automatically defined inside /etc/hosts by Docker&#xA;  }&#xA;&#xA;  server {&#xA;    listen *:80;                # Listen for incoming connections from any interface on port 80&#xA;    server_name &amp;quot;&amp;quot;;             # Don&#39;t worry if &amp;quot;Host&amp;quot; HTTP Header is empty or not set&#xA;    root /usr/share/nginx/html; # serve static files from here&#xA;&#xA;    location /app/ {            # catch any requests that start with /app/&#xA;      proxy_pass http://app/;   # proxy requests onto our app server (i.e. a different container)&#xA;                                &#xA;     # NOTE: If you don&#39;t put a forward slash / at the end of the upstream name&#xA;     #       then you&#39;ll find nginx passes the request as /app/ rather than just /&#xA;     #       Putting / after the upstream name means it acts more like the alias directive&#xA;     #       If I kept it as http://app; then I would&#39;ve needed to add a /app/ route to Sinatra&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With this change made, we can now make the following requests successfully:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;curl http://$(boot2docker ip):&amp;lt;dynamic_port_number&amp;gt;/app/&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;curl http://$(boot2docker ip):&amp;lt;dynamic_port_number&amp;gt;/app/foo&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This was a bit of a whirlwind run through to getting a simple nginx reverse proxy set-up with Docker. You can obviously swap out the Ruby backend with whatever technology stack is more appropriate (e.g. Node, Clojure, Scala&amp;hellip; whatever).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here, if you&amp;rsquo;re new to nginx (like I am) you can start to experiment with the many other features nginx provides. Enjoy!&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/docker-nginx/</guid>
      <link>https://www.integralist.co.uk/posts/docker-nginx/</link>
      <pubDate>Tue, 04 Aug 2015 00:00:00 +0000</pubDate>
      <title>Setting Up Nginx With Docker</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;⚠️  This post was originally written for &lt;a href=&#34;https://davidwalsh.name/designing-simplicity&#34; target=&#34;_blank&#34;&gt;David Walsh back in 2015&lt;/a&gt;. I&amp;rsquo;ve since decided to reproduce it here for my own records - Integralist: August, 2017.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Before we get started, it&amp;rsquo;s worth me spending a brief moment introducing myself to you. My name is Mark (or &lt;a href=&#34;https://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;@integralist&lt;/a&gt; if Twitter happens to be your communication tool of choice) and I currently work for BBC News in London England as a principal engineer/tech lead; and I&amp;rsquo;m also the author of &amp;ldquo;&lt;a href=&#34;http://www.apress.com/9781484202517&#34; target=&#34;_blank&#34;&gt;Pro Vim&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Quick shout out to &lt;a href=&#34;https://twitter.com/stevenjack85&#34; target=&#34;_blank&#34;&gt;Steven Jack&lt;/a&gt; who took the time to review this post. A lot of what we&amp;rsquo;ve done right, he either helped instigate or was a fundamental part of its success&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The &amp;ldquo;responsive&amp;rdquo; BBC News website receives approximately 8 million visits per day (that&amp;rsquo;s on average for a quiet news day). Those numbers will go much higher once the responsive site replaces the current static desktop offering and starts to incur many more users. But for the moment that gives a rough idea of the sort of traffic we get on a daily basis.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post aims to take a whirlwind tour of different code design and architectural discussion points that have cropped up at one point or another while I&amp;rsquo;ve been working at the BBC. We will be peeking at some top-level system infrastructure in a bid to provide you with some &amp;ldquo;food for thought&amp;rdquo; on these topics. I&amp;rsquo;ll talk about some techniques and tools that work for us, and we&amp;rsquo;ll also see some that didn&amp;rsquo;t work quite so well. I&amp;rsquo;ve always been intrigued by how other developers work and think about different types of problems, so let&amp;rsquo;s consider this a knowledge sharing experience from me to you.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the thoughts and comments here are my own and do not necessarily represent those of my employer. Yup, I had to go there&amp;hellip; just in case&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now some readers will probably not have to worry about the same sort of scalability problems the BBC has to deal with, when designing/building systems and applications. But this isn&amp;rsquo;t to say the information and thoughts I&amp;rsquo;m going to share with you here in this post aren&amp;rsquo;t transferable. In fact, much of what I&amp;rsquo;ll be discussing are concepts that can be utilized in applications of any size (because good design is effective at any scale).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this post covers very little front-end technologies and techniques. That topic of discussion is much more vast and has been covered substantially over the past few years (especially the topic of performance, which has - since ~2007 - been brought into the mainstream mindset of front-end engineers by &lt;a href=&#34;http://stevesouders.com/&#34; target=&#34;_blank&#34;&gt;Steve Souders&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;So without further ado, let&amp;rsquo;s begin&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;complexity-vs-complicated&#34;&gt;Complexity vs Complicated&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When describing a piece of software, you&amp;rsquo;ll often here the words &amp;ldquo;complex&amp;rdquo; and &amp;ldquo;complicated&amp;rdquo; used. We need to be careful when using these phrases that we select the one that accurately expresses our opinion. For example, some one might say a piece of software is &amp;ldquo;complicated&amp;rdquo;, when really they mean it&amp;rsquo;s &amp;ldquo;complex&amp;rdquo; (and vice versa). Unfortunately the definition of both these words doesn&amp;rsquo;t help to clarify which we should use and in which context. This can make it harder to express what we really mean to say.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me, describing something as being &amp;ldquo;complicated&amp;rdquo;, infers a negative connotation (it has used either bad logic or implemented a bad design). Usually the phrase &amp;ldquo;this feels over-engineered&amp;rdquo; will follow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The word &amp;ldquo;complexity&amp;rdquo; on the other hand represents to me a varying value (in that it&amp;rsquo;s dependent on the system being reviewed) and so it feels like a more appropriate term to use when recognizing the software&amp;rsquo;s design has evolved and become much larger over time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also still apply the term &amp;ldquo;complex&amp;rdquo; to individual units of code. If a class or function is taking on too much responsibility then it can feel like it&amp;rsquo;s becoming too complex, and subsequently some of its logic will need to be extracted into another class or function. This is apposed to, let&amp;rsquo;s say, a function using a bad algorithm, in which you may identify that code as being &amp;ldquo;complicated&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now if a piece of software has a lot of moving parts (most applications do) and you have a difficult time building a mental model of it all, and subsequently are not able to follow its thread very easily, doesn&amp;rsquo;t necessarily mean the application is &amp;ldquo;complicated&amp;rdquo;. Lots of small, simple, and non-complicated functional components can be composed together to create a much larger system and subsequently can make the overall picture become a little harder to decipher. This is what makes software &amp;ldquo;complex&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Good code design doesn&amp;rsquo;t always help you to see the bigger picture. What good code design does help with is making smaller functional units much more easily understood and composable (e.g. SRP - Single Responsibility Principle; one part of &lt;a href=&#34;http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29&#34; target=&#34;_blank&#34;&gt;S.O.L.I.D&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason I&amp;rsquo;m mentioning this upfront is because I do not want people to walk away (mistakenly) thinking their existing software, or its architecture, is fundamentally flawed or broken. You must always take a critical eye to your systems/applications; but be aware that although they may be &amp;ldquo;complex&amp;rdquo;, that might be the natural order of things. A complete rewrite is not necessarily required.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;promoting-simplicity&#34;&gt;Promoting simplicity&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;With the discussion of complexity behind us, let&amp;rsquo;s move onto what it means for software to be &amp;ldquo;simple&amp;rdquo;. Why is simplicity a good thing? Simplicity itself is defined as:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;the quality or condition of being easy to understand or do&amp;rdquo;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If a piece of software is considered &amp;ldquo;simple&amp;rdquo;, then chances are it has been found to be easy to understand and easy to reason about. Simple software is also easy to manipulate and apply changes to. &lt;a href=&#34;http://en.wikipedia.org/wiki/Kent_Beck&#34; target=&#34;_blank&#34;&gt;Kent Beck&lt;/a&gt; (renowned author of many top quality software engineering books and the co-creator of Extreme Programming, which then evolved into &amp;ldquo;agile&amp;rdquo; practices) made the following statement back in 2012:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;make the change easy, then make the easy change&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;What Kent was referring to, was that for a piece of software to be easily changed you needed to simplify its design in such a way for it to be able to facilitate a future requirement.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Simplicity will also tend to result in less bugs, because there are less complicated moving parts. The irony of all this, is that writing and designing code to be simple is usually quite a complex task. It&amp;rsquo;s important to realize that &lt;code&gt;simplicity != easy&lt;/code&gt;. Lots of people fail to make the distinction between the two.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Simplicity can also (not always mind you) help towards other goals such as reusability and portability of your software.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;naming-things&#34;&gt;Naming things&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Phil Karlton (Netscape engineer; sadly killed in 1997) once said:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;There are only two hard things in Computer Science: cache invalidation and naming things&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ve likely heard this quote said many times already throughout your career. There&amp;rsquo;s a reason for that: because it&amp;rsquo;s a painfully universal truth. Nothing causes our team to sit pondering in deadlock (or maybe livelock would be more accurate) together, than when we&amp;rsquo;re trying to figure out what to call our new library.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People underestimate how important it is to properly name things. Whether it be a new open-source library, a class, a function, a variable - it doesn&amp;rsquo;t matter what it is - there is a potential to cause confusion and in some cases real problems if named badly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There&amp;rsquo;s the classic front-end dilemma where a developer creates a class called &lt;code&gt;.red-banner&lt;/code&gt; because it is applied to a component that is, well, red; and then a month later the designers step in and change the component to have a blue background. Great, now this doesn&amp;rsquo;t seem like much of an issue but scale up the size of the site and the potential places where that class gets used; now add on top of that a little more ambiguity and you&amp;rsquo;ve suddenly incurred &amp;ldquo;tech debt&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now that was just a super basic example. In practice you&amp;rsquo;ll find naming issues everywhere. Does the name of your class truly represent its intent. Is the name you&amp;rsquo;ve used too explicit; by that I mean does it reference a particular object type or design aspect that restricts the class from being truly generic?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if you have a class that acts as a mediator between two objects, have you named it &amp;ldquo;MessageBus&amp;rdquo; because you&amp;rsquo;re currently using the Observer/PubSub pattern? What if the class changes functionality to some other pattern or software? Surely naming it to be &lt;code&gt;ComponentMediator&lt;/code&gt; would be better, as that is clear enough to express the intent of the class while open enough for the implementation details to change in future (sort of like a less concrete &lt;a href=&#34;http://en.wikipedia.org/wiki/Open/closed_principle&#34; target=&#34;_blank&#34;&gt;Open/Closed principle&lt;/a&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Either way, you need to not underestimate the problems and confusion that can be caused by a badly named object/class/thing. Be vigilant, and if you&amp;rsquo;re unsure then discuss it with your team. But be warned, this isn&amp;rsquo;t always a quick or obvious process.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;growth&#34;&gt;Growth&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Applications are organic; they grow and evolve over time, which can increase their complexity. But software also needs to contend with growing popularity, which means increased traffic and the need to always be available (i.e. up and running!). All software should have a modicum of scalability in mind when within the design stages. It would be foolish not to at least consider what happens when your system comes under heavy load.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The BBC has specific platform teams dedicated to carrying out load tests before any major software release. The benefit of this is to ensure that a new piece of software can run safely while handling x number of requests per second. The load test results help to indicate what an application&amp;rsquo;s threshold will be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My team typically uses a command line tool called &lt;a href=&#34;http://manpages.ubuntu.com/manpages/hardy/man1/siege.1.html&#34; target=&#34;_blank&#34;&gt;Siege&lt;/a&gt; to stress test our applications &lt;em&gt;before&lt;/em&gt; requesting a full load test from our platform team, as this can help weed out any silly mistakes before going through official channels.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The BBC also utilizes &lt;a href=&#34;https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey&#34; target=&#34;_blank&#34;&gt;Chaos Monkey&lt;/a&gt; (a tool developed by Netflix) to help verify the resiliency of its systems. Chaos Monkey itself has been instrumental in how we have started to look at designing and architecting our systems and applications.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The purpose of Chaos Monkey is to bring down (at random) a server instance that is currently running. This sounds like a crazy thing to do within your production environment; but the reality is it forces you to think long and hard at the design stage of your applications to ensure they are resilient and capable of being brought back up automatically.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At any moment, Chaos Monkey could bring down one of our servers running a public facing and highly critical application. This helps bring about an important realization that you need to start considering solutions before writing any code. By really thinking about the design up front, you avoid issues where you may find your existing software just isn&amp;rsquo;t resilient enough and is going to cause unacceptable service outages; and yet the existing system may well be in such a state that it doesn&amp;rsquo;t facilitate an easy path to becoming scalable (e.g. a monolithic application with many responsibilities and domain areas, will introduce a massive single point of failure and is going to take a long time to refactor).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Solutions to the problem of resiliency and scalability (at the design stage) could, for example, involve building microservices to help isolate single points of failure. As well as implementing stateless/immutable servers, where by you can bring up a new instance and not worry that critical state has been lost (along with service discovery mechanisms such as &lt;a href=&#34;https://www.consul.io/&#34; target=&#34;_blank&#34;&gt;Consul&lt;/a&gt; or &lt;a href=&#34;https://github.com/coreos/etcd&#34; target=&#34;_blank&#34;&gt;etcd&lt;/a&gt;). Infrastructure as code is another important concept and can be achieved using technology such as &lt;a href=&#34;http://aws.amazon.com/cloudformation/&#34; target=&#34;_blank&#34;&gt;AWS CloudFormation&lt;/a&gt; (which we&amp;rsquo;ll discuss in more detail later on in this post).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Scaling a system to accommodate more users isn&amp;rsquo;t a free lunch; doing so can cause the introduction of inherent complexity, as it needs to consider many different mechanisms for facilitating an increase in traffic.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically the first thing developers do (before considering more extreme architectural changes) is to try running their code in parallel (or support more concurrent operations). There is nothing necessarily wrong with that, unless your code isn&amp;rsquo;t &amp;ldquo;&lt;a href=&#34;http://en.wikipedia.org/wiki/Thread_safety&#34; target=&#34;_blank&#34;&gt;thread safe&lt;/a&gt;&amp;rdquo;. Fixing the issue of thread safety isn&amp;rsquo;t always straight forward and if you&amp;rsquo;re new to the concept of multi-threaded code then you&amp;rsquo;ll likely hit a few stumbling blocks as you slowly start to understand the problem space.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re interested in understanding thread safety (and the different concurrency abstractions) in more detail then I recommend you take a read of the following article &amp;ldquo;&lt;a href=&#34;/posts/concurrency/&#34;&gt;Thread Safe Concurrency&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Along side the process of trying to speed up code by multi-threading, you&amp;rsquo;ll nearly always want to have your application scale automatically based upon the current needs of the system. If you&amp;rsquo;re application is running on an infrastructure that is designed to scale &amp;ldquo;horizontally&amp;rdquo; (e.g. it dynamically creates new server instances running your application) then you will quickly start to introduce the problem of data consistency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Data consistency is where the &amp;ldquo;CAP theorem&amp;rdquo; comes into play. CAP states:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;it is impossible for a distributed computer system to simultaneously provide all three of the following guarantees: consistency, availability and partition tolerance&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;What this means in practice is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Consistency: all nodes in your system should have the same view of the world&lt;/li&gt;&#xA;&lt;li&gt;Availability: a guaranteed response (whether a success or fail message)&lt;/li&gt;&#xA;&lt;li&gt;Partition tolerance: the system as a whole continues to function even when a part of the system completely fails (or messages between decoupled systems are lost)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The problem of growth can also affect the decisions made from both back and front-end development perspectives. For example, when building real-time data processing applications, you have the option of either long polling and handling back pressure vs Web Sockets vs Server-Sent Events; all with varying browser support, and each of these options opens up a different set of concerns regarding how the back-end system is architectured.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem of growth and scaling applications can be simplified by splitting up your application into well defined, isolated, functional units. If you&amp;rsquo;re working with a single monolithic application, try to imagine what it would look like if split up into multiple isolated services. Where each part of the application communicated with another service via HTTP (or TCP, or via some other low level mechanism). What would the system look like? Don&amp;rsquo;t you think it would be easier to analyze and scale individual services than one massive monolithic application?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This leads us nicely onto the topic of &amp;ldquo;Microservices&amp;rdquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-micro-fallacy&#34;&gt;The micro fallacy?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of &lt;sup&gt;2014&lt;/sup&gt;&amp;frasl;&lt;sub&gt;2015&lt;/sub&gt;, microservices is a bit of a buzzword. Lots of organizations and companies are talking about designing microservices and using tools (like &lt;a href=&#34;https://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt;) to enable them to more easily build and scale their growing set of microservices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I felt it was important to make a very quick mention of the fact that people tend to see a monolithic application as bad and a system of small services as good. While I would tend to agree, I would state that I&amp;rsquo;ve sat on both sides of the fence and each one has their pros and cons. If you&amp;rsquo;re working on a small scale system then a microservice design can be extra overhead and unnecessary complexity you don&amp;rsquo;t need. Just because all the cool kids are drinking the microservices koolaid doesn&amp;rsquo;t mean you have to (or should). Always take a critical eye to your design and evaluate things based on your own situation/requirements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that being said, I personally see microservices as the way we will, and should, be designing and building &lt;em&gt;large scale&lt;/em&gt; systems moving forward; as overall it offers many more benefits compared to old school monolithic applications. It&amp;rsquo;s important when designing services that you split up the responsibilities in your application appropriately, and try to find a sweet spot between separation of concerns and domains vs fragmentation.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;decoupling-systems&#34;&gt;Decoupling systems&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When considering the design of a complex system, we ideally want to decouple our code by individual domain areas. The reason for this is that it allows us to scale any particular part of the system that becomes a bottle neck; rather than carrying out a blanket scale up of the entire system; which is not only expensive but impractical.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the following diagram as a basis, let&amp;rsquo;s consider an application where the user uploads an image (1) and the server resizes the image (2) and places the newly created image into an &lt;a href=&#34;http://aws.amazon.com/s3/&#34; target=&#34;_blank&#34;&gt;AWS S3&lt;/a&gt; bucket (3). The server is expected to return an auto generated URL to the user (4), which when shared with and visited by another user will show the resized image.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/bad-architecture.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/bad-architecture.png&#34; alt=&#34;Bad Architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This architecture will not scale very well, nor very easily.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for brevity I&amp;rsquo;ve left out some details from this architecture, such as persisting URLs&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Instead the process should be more decoupled, like so (see below diagram): user uploads an image (1), the server stores the image into an S3 bucket in its original form (2) and sends a message to an &lt;a href=&#34;http://aws.amazon.com/sqs/&#34; target=&#34;_blank&#34;&gt;AWS SQS&lt;/a&gt; queue (3). The server then returns a message to the user to inform them the image is being processed along with the auto generated URL (4).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the mean time, a separate service is polling the queue for messages (5). The service will read the message (which can include the location of the source image in S3) and then retrieves the relevant image from S3 (6) so it can resize the image (7) and replace the image in S3 with the resized version (8), or whatever needs to happen at that point.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/better-architecture.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/better-architecture.png&#34; alt=&#34;Better Architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So this design might not be perfect, but what&amp;rsquo;s better about this architecture is that we&amp;rsquo;ve decoupled the various parts of the overall system that previously would&amp;rsquo;ve made scaling the application much harder. We&amp;rsquo;re now in a position to scale up the back-end service (the service that polls the queue and resizes the images) separately from the front-end system which handles the user upload.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the user visits the auto generated URL before the image has been processed, then a message can be displayed to indicate the image is still being processed. Again, this isn&amp;rsquo;t perfect but it has freed up the user to go off and do other things, they&amp;rsquo;re not chained to the browser window watching a message that says &amp;ldquo;Processing&amp;hellip;&amp;rdquo; for the next few minutes (or longer depending on how much load your system is under).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One practical improvement here is that the new system is much more fault tolerant than the original. In the original system, if the server crashed then the user would likely be returned a &lt;a href=&#34;http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500&#34; target=&#34;_blank&#34;&gt;500 HTTP Status Code&lt;/a&gt;, whereas with the new system the user can continue to use the website (they&amp;rsquo;ll see the message &amp;ldquo;Image waiting to be processed&amp;rdquo; until a new back-end server instance can be brought up, where by it&amp;rsquo;ll continue to process messages off the image queue).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;fault tolerance is often referred to as &amp;ldquo;partition tolerance&amp;rdquo;; I mentioned this earlier when discussing CAP Theorem.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the above example we&amp;rsquo;ve used queues to help decouple the individual parts of our software system (similar in spirit to creating microservices), but there are other mechanisms for decoupling code such as using a &lt;a href=&#34;http://en.wikipedia.org/w/index.php?title=Message-oriented_middleware&amp;amp;redirect=no&#34; target=&#34;_blank&#34;&gt;message bus&lt;/a&gt;. Best to research different techniques to see how your architecture could be designed to utilize them to avoid problems with scaling.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;depending on the purpose of the above application, you might decide that displaying the unoptimized image would be better than displaying a message to the user to say the image is still being processed. The reason I didn&amp;rsquo;t do that here was because of performance reasons (the size of the image could be very large and not something you want a mobile user to have to download - especially if they&amp;rsquo;re traveling with a poor network connection)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;broker-renderers&#34;&gt;Broker/Renderers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At BBC News in London, my team have released an open-source framework written in Ruby called &lt;a href=&#34;https://github.com/BBC-News/Alephant&#34; target=&#34;_blank&#34;&gt;Alephant&lt;/a&gt;, which abstracts a common pattern we find useful for decoupling our data driven applications.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve used this particular framework on quite a few projects over the past year and a half; such as the Scottish Referendum, the local and general elections, an upcoming redesign of BBC Newsbeat as well as the World Service Kaleidoscope project (dynamic serving of image based content to devices with poor support for non-latin fonts).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;I&amp;rsquo;d like to give a shout out to &lt;a href=&#34;https://twitter.com/kenturamon&#34; target=&#34;_blank&#34;&gt;Robert Kenny&lt;/a&gt; (formerly of BBC, and now working at the Guardian) as the original inspiration and developer for the Alephant framework. Although it has changed quite significantly since its inception, it was his solid work that helped to support some very important and high traffic events.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The pattern is effectively a &amp;ldquo;broker&amp;rdquo; (i.e. mediator) and a &amp;ldquo;renderer&amp;rdquo;. With this pattern, user requests are routed through to the relevant broker, who then decides where the request(s) should be directed. On the other end of the design are a bunch of &amp;ldquo;renderer&amp;rdquo; services, and their role changes depending on the type of model we use: push or pull.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s explore this a little further:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Broker: a service which accepts requests (requests are handled differently depending on the model)&lt;/li&gt;&#xA;&lt;li&gt;Renderer: a service which gets data from an endpoint and renders it into HTML (or whatever format is required)&lt;/li&gt;&#xA;&lt;li&gt;Models: &amp;ldquo;push&amp;rdquo; and &amp;ldquo;pull&amp;rdquo; (we&amp;rsquo;ll see what each of these are in the next section)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;push&#34;&gt;Push&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The push model is similar to the &amp;ldquo;image processing&amp;rdquo; architecture we discussed in the previous section, in that we&amp;rsquo;re using a queue to decouple our services.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the push model, messages are placed on a queue. These messages contain data we want rendered into HTML (to use a real world scenario: the election results are pushed into a queue). We then have a renderer service running and this service polls the queue for messages. When a message (e.g. election result) is received we then process that message, render it into HTML and store that rendered content in a storage area (this could be any cloud based storage system, such as AWS S3, for example).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The renderer service is easily scalable because we can set alarm thresholds that indicate whether there are too many messages on a queue (i.e. if there are lots of messages waiting on the queue, then our renderer service isn&amp;rsquo;t processing them quick enough and so we need to scale up more renderer instances to handle the message load).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;AWS SQS doesn&amp;rsquo;t guarantee a delivery order (this isn&amp;rsquo;t true of all queues - so if delivery order is important to you then there are other queue types available) and so care needs to be taken to ensure messages don&amp;rsquo;t get overwritten. We found this type of contention could happen when scaling up our Renderer service.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To give you an example, imagine we have two Renderers: R1 and R2. Both of them take a message off the queue. R1 gets version 1 of message &amp;ldquo;A&amp;rdquo;, while R2 gets an updated version 2 of message &amp;ldquo;A&amp;rdquo;. If R2 finishes first, then R1 will finish last and subsequently the older version of the message will be stored and used (a real and practical example of this is getting election results pumped onto a queue; the vote count for a particular party needs to be the latest numbers).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid this contention we use a document store (AWS DynamoDB) to track the version of a message and when we come to store the rendered content of our data in our storage facility, we make sure the key we need to lookup that rendered content also includes its version number.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this is something we did before DynamoDB added its &amp;ldquo;Conditional Put&amp;rdquo; feature&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The broker in the push model, receives a request for a component, and is able to use the information it is provided to lookup the latest rendered version of a message. It does this by constructing a key that determines the location of the latest version within our storage facility. These lookups are also heavily cached to allow us to handle as much load as possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following diagram gives you a top-level view of this architecture:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/broker-renderer-pattern-push-model.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/broker-renderer-pattern-push-model.png&#34; alt=&#34;Broker Renderer Pattern Push Model&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for brevity, in the above diagram, I&amp;rsquo;m not demonstrating either the caching of broker requests or the sequencing requirements (i.e. the storing off the version of a message into DynamoDB). As mentioned before, some queues have different guarantees and so I didn&amp;rsquo;t want the diagram to be too tightly coupled to DynamoDB&amp;rsquo;s implementation&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;There is another concern that we&amp;rsquo;ve accounted for, but I&amp;rsquo;ve left out for brevity, which is AWS S3&amp;rsquo;s &amp;ldquo;eventual consistency&amp;rdquo; model. But I think for now this explanation should be enough to give you an idea of how the pattern works.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;pull&#34;&gt;Pull&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The pull model is simpler in that it doesn&amp;rsquo;t rely on a message queue for its data. In this model our renderers are more &amp;ldquo;connected&amp;rdquo; to our broker.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By this I mean: the broker will receive a request for a component, and it will use the information that has been passed with the request to lookup the relevant renderer it needs to contact (service discovery), in order to retrieve the requested component. The renderer service has a remote endpoint built in, that it uses to make requests to, to retrieve the data required for a successful render to happen (so no storing of rendered components into a storage facility; we&amp;rsquo;re dynamically renderering data upon request).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason we created this model was because we had certain domain models where the data changes were vast, and would require a large amount of up-front rendering that might potentially never be seen by (i.e. requested from) an end user. The BBC&amp;rsquo;s Market Data pages were an example of this, where some business data would rarely be viewed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following diagram gives you a top-level view of this architecture:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/better-architecture.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/better-architecture.png&#34; alt=&#34;Better Architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for brevity, in the above diagram, I&amp;rsquo;m not detailing the complexity of how you feed information to a broker so it knows which renderer to interrogate to satisfy the user&amp;rsquo;s request&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;There are some pitfalls to this model though. The main one being we&amp;rsquo;re coupling our data to our templates. For example, if a change is required within the template (let&amp;rsquo;s say a HTML &lt;code&gt;class&lt;/code&gt; attribute is added to an element; but all other &amp;ldquo;structure&amp;rdquo; of the content is the same), then it would require a complete re-render of the component.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We had experimented (briefly) with rendering the data itself, and then letting a layer further downstream handle the template composition, but this resulted in other complications. With looming deadlines and concerns regarding forcing responsibility for the templates onto some other part of the system, we decided to postpone.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;design-and-architecture&#34;&gt;Design and architecture&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The reason we find the broker/renderer pattern so useful is because of how we&amp;rsquo;ve designed the individual libraries that make up the framework. They allow for consumers of the libraries to provide custom configuration to support their own specific requirements. We also use the strategy design pattern, for the pull model, which allows a consuming application to inject the logic the library should use to determine how to construct remote data endpoints (in case the storage location path is different for your set-up).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the essence of composability, it&amp;rsquo;s like lego bricks slotting together to form a large piece. Although you can utilise individual aspects of the frameworks that fit your needs (because each library is self sufficient in providing isolated functionality), the framework works best when utilized to form the broker/renderer pattern we primarily designed the framework around.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s an interesting mix of SRP (Single Responsibility Principle) and the composability of FP (Functional Programming).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-low-can-you-or-should-you-go&#34;&gt;How low can you (or should you) go?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For any performance critical (and scalable) application, it&amp;rsquo;s important to consider the overhead of certain technologies. For example, when it came to building the Alephant framework (discussed in the previous section), we decided that &lt;a href=&#34;http://sinatrarb.com/&#34; target=&#34;_blank&#34;&gt;Sinatra&lt;/a&gt; (a very popular Ruby web framework that is preferred over a monolithic framework such as &lt;a href=&#34;http://rubyonrails.org/&#34; target=&#34;_blank&#34;&gt;Ruby on Rails&lt;/a&gt;) was still too bulky for our needs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By that I mean, it had all sorts of web related features that we didn&amp;rsquo;t need for our application. So we opted for the lower level (almost, but not quite, bare metal) Rack interface. Depending on your requirements, it may even be worth considering whether you drop down a level from HTTP to TCP or even UDP socket protocols if you genuinely don&amp;rsquo;t need the extra overhead of HTTP for communicating between services (e.g. you may have internal services running on your server instances that aren&amp;rsquo;t publicly exposed).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to realize that stripping back the layers of complexity can help to better reveal the intent of your code. Making it easier to understand and to reason about.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;language-agnostic-templates&#34;&gt;Language agnostic templates&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At the BBC we discovered (the hard way) that our approach for managing the storage and deployment of front-end components wasn&amp;rsquo;t scalable. The problem stemmed from a more traditional method of structuring front-end applications, which meant separating JavaScript, CSS and images into separate folders.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s for the moment consider the JavaScript folder: within this folder we would have multiple &amp;ldquo;modules&amp;rdquo; (a module being a single JavaScript file and represents an isolated piece of functionality). A single HTML component could well have multiple functional requirements meaning it would be dependent on multiple JavaScript modules.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This shouldn&amp;rsquo;t appear strange to any one as the majority of developers separate their concerns in this way. The downside though to this approach is that when your system begins to expand and evolve you will start to notice the problem of fragmentation and being tightly coupled to the application the components &lt;em&gt;currently&lt;/em&gt; resides within.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By that I mean: if you have a HTML component and it relies on JavaScript modules X and Y as well as CSS files A and B, then you can&amp;rsquo;t easily reuse that component within another system without either replicating the directory structure that the current application utilizes or making code changes to reflect the location of dependencies within the new system. On top of that, the dependency tree for each component was getting larger and harder to visualize and maintain (as more and more functionality was being added to certain components).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this classic architectural model you lose (or at least complicate) maintainability, reusability, portability and even the ability to isolate components for easier testing. The ability to share components across teams (who work on different platforms) was also proving difficult as we were being forced to duplicate content, and this led to the decision to create a specification that describes how to build truly atomic components that can be easily consumed by varying services.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Enter &lt;a href=&#34;https://twitter.com/pgchamberlin&#34; target=&#34;_blank&#34;&gt;Peter Chamberlin&lt;/a&gt; and Liam Wilkins to take inspiration from both &lt;a href=&#34;http://bradfrost.com/blog/post/atomic-web-design/&#34; target=&#34;_blank&#34;&gt;Brad Frost&amp;rsquo;s atomic design&lt;/a&gt; and &lt;a href=&#34;http://ianfeather.co.uk/a-maintainable-style-guide/&#34; target=&#34;_blank&#34;&gt;Ian Feather&amp;rsquo;s Rizzo&lt;/a&gt; and helped to resolve this divide by creating the open-source project &amp;ldquo;&lt;a href=&#34;https://github.com/BBC-News/chintz&#34; target=&#34;_blank&#34;&gt;Chintz&lt;/a&gt;&amp;rdquo; which combines the best aspects of both the former projects.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;this project is still WIP (work in progress) but we encourage the community to get involved and create an open discussion around how the specification evolves&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The driving force behind this specification was for it to be language agnostic. This was a fundamental requirement in allowing different language platforms to consume these components. The processing of components has a few simple requirements:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;define a folder structure that will contain the components&lt;/li&gt;&#xA;&lt;li&gt;define a manifest that describe the dependencies for a given component&lt;/li&gt;&#xA;&lt;li&gt;implement a client parser that resolves the dependencies within the manifest&lt;/li&gt;&#xA;&lt;li&gt;build an app that consumes the client parser&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In the following diagram we show how two separate platforms (PHP and Ruby) consume a parser specific to their language to resolve the dependencies for a given component and serve up the component(s) in the most appropriate way for their platform:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/chintz-specification.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/chintz-specification.png&#34; alt=&#34;Better Architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are currently two (WIP) client parsers we&amp;rsquo;ve open-sourced:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/BBC-News/chintz-php&#34; target=&#34;_blank&#34;&gt;PHP&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/BBC-News/chintz-ruby&#34; target=&#34;_blank&#34;&gt;Ruby&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we also hope to implement one utilizing JavaScript/Node&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;A manifest file could look something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;name: exampleElement&#xA;dependencies:&#xA;  css: [ base/base.css, base/typography.css ]&#xA;  js: [ exampleElement/someOtherFilename.js ]&#xA;  elements: [ anotherThing ]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This manifest file makes it simple to understand the complexity of a single component.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The hope moving forward is for our internal component pattern library, built on top of Chintz, to be utilised across teams working on different platforms. For example, the BBC News core team work on a traditional PHP platform, while the Elections Presentation team develop cloud based components (generated with Ruby) that are consumed by the core team&amp;rsquo;s platform.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;automation-and-duplication&#34;&gt;Automation and Duplication&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When dealing with large software systems, you&amp;rsquo;ll need to ensure you&amp;rsquo;re automating things and reducing the amount of repeatable work you have. This is essential when managing software of any substantial scale.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a few ways my team automates and reduces duplication (you&amp;rsquo;ll likely find similar concepts and processes in many other teams and products):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Continuous Delivery&lt;/li&gt;&#xA;&lt;li&gt;AWS CloudFormation&lt;/li&gt;&#xA;&lt;li&gt;Custom library abstractions&lt;/li&gt;&#xA;&lt;li&gt;Containerisation via Docker&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;continuous-delivery&#34;&gt;Continuous Delivery&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Deploying software within the BBC can be a complex process as we have lots of moving parts to take code from a developer&amp;rsquo;s laptop and into a working release that&amp;rsquo;s deployed to our cloud infrastructure. To make deploying software as simple as possible, we have since developed a complicated deployment pipeline to try and help achieve the end goal of having a &amp;ldquo;simple&amp;rdquo; release process.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Notice I said &amp;ldquo;complicated&amp;rdquo; :-(&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;We currently use the &lt;a href=&#34;http://jenkins-ci.org/&#34; target=&#34;_blank&#34;&gt;Jenkins&lt;/a&gt; continuous integration server to support our deployment process. Jenkins is an industry standard piece of software and no organization should be releasing software without some form of CI.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we commit code into GitHub we trigger a build job on Jenkins that builds an RPM that we&amp;rsquo;ll want to deploy onto our distributed cloud servers. But before that deploy can happen we need to make sure that our software is safe to release. This means that we trigger another job that verifies this via different unit and integration tests for our integration environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If all is well we then trigger the next set of jobs that do the same for our test environment and once again for our live environment. If any one of these jobs fail then the deployment to that environment will be marked as failed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the reason I used the word &amp;ldquo;complicated&amp;rdquo; earlier (rather than the more ideal &amp;ldquo;complex&amp;rdquo; - see the start of this blog post for the difference between them) is because we&amp;rsquo;ve fundamentally reached the limits of what the Jenkins software can handle and this has resulted in a solution that may work (most of the time) but is far to complicated to be maintainable. If a build breaks then it can be very hard to follow the trail because Jenkins wasn&amp;rsquo;t really designed with Continuous Delivery in mind.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although Jenkins provides plugins to help extend its functionality so it can support more complex deployment pipeline processes, the various plugin options available aren&amp;rsquo;t as good as they could be, and most don&amp;rsquo;t offer a clear visibility of the status of a particular group of jobs. This is where something like &lt;a href=&#34;http://www.go.cd/&#34; target=&#34;_blank&#34;&gt;GOCD&lt;/a&gt;, which aims to streamline the build-test-release life cycle, would come into the equation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Jenkins has served its purpose, and we&amp;rsquo;ve found that it&amp;rsquo;s no longer a complex piece of software, but has moved into being more of a complicated one instead. If you find yourself in a similar situation, then this should be an indication that you need to be constantly monitoring your processes and evaluating their effectiveness.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our Jenkins set-up works, so it&amp;rsquo;s &amp;ldquo;good enough&amp;rdquo; for the moment. But don&amp;rsquo;t fall into the trap of accepting the current system as being &amp;ldquo;good enough&amp;rdquo;. The moment you start feeling any pain setting up or implementing a piece of software, then much like a good code smell indicates the need to refactor, you should start re-evaluating how the situation can be improved. This is something we&amp;rsquo;re actively doing at the moment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember not to make any rash decisions (e.g. let&amp;rsquo;s implement a whole new CI/CD system) that could potentially leave you with more tech debt than you initially realized; especially if your team has very tight deadlines already. Adding to your workload isn&amp;rsquo;t a sensible decision. Changing your deployment process is an incredibly important decision and so you must be absolutely certain you&amp;rsquo;ve exhausted all other options first.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;aws-cloudformation&#34;&gt;AWS CloudFormation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re unfamiliar with CloudFormation, then I&amp;rsquo;ll refer you to the official definition:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;AWS CloudFormation gives developers and systems administrators an easy way to create and manage a collection of related AWS resources, provisioning and updating them in an orderly and predictable fashion&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;http://aws.amazon.com/cloudformation/&#34; target=&#34;_blank&#34;&gt;AWS CloudFormation&lt;/a&gt; service is great for two primary reasons:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;It automates the ability to start up and provision a consistent and reproducible infrastructure&lt;/li&gt;&#xA;&lt;li&gt;It facilitates the ability to version control your infrastructure&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;With regards to the first point, this also facilitates a seamless setup of different deployment environments. This means we can configure each specific environment (using CloudFormation parameters) to allow, as an example, an integration and test environments to have very small EC2 server instances while stage and production environments have larger server instances (helping to keep costs down in our non-critical environments such as integration and test).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Depending on your experience with AWS you may feel like CloudFormation falls into the &amp;ldquo;complicated&amp;rdquo; category. This is very much a subjective opinion though, as learning CloudFormation may well (initially) feel quite confusing and complicated; the end result is a much simpler, quicker and easier way to build/automate a fully provisioned system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are also tools available that can help ease writing raw CloudFormation (which is just a JSON file). You could go one abstraction level up and start writing CloudFormation stacks using &lt;a href=&#34;http://yaml.org/&#34; target=&#34;_blank&#34;&gt;YAML&lt;/a&gt; or you could use a language specific DSL such as &lt;a href=&#34;https://github.com/stevenjack/cfndsl/&#34; target=&#34;_blank&#34;&gt;CFNDSL&lt;/a&gt; (which is a Ruby DSL).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;custom-library-abstractions&#34;&gt;Custom library abstractions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Most of our projects are built up from a baseline of abstract/generic libraries (RPMs) that provide us with specific default functionality. These abstractions make it very easy for us to construct a complex software stack without having to constantly repeat ourselves.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, consider the following three libraries:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Component Base&lt;/li&gt;&#xA;&lt;li&gt;JRuby Application&lt;/li&gt;&#xA;&lt;li&gt;Puma Init&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Each one of these libraries will add their own &amp;ldquo;profile&amp;rdquo; to &lt;code&gt;/home/component&lt;/code&gt;. Each library will load their profile, which will add a hook for another downstream consuming library to utilize.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Component Base: creates &lt;code&gt;/home/component/.bash_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The profile tries to source &lt;code&gt;/home/component/.custom_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;JRuby Application: creates &lt;code&gt;/home/component/.custom_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The profile tries to source &lt;code&gt;/home/component/.component_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Puma Init: creates &lt;code&gt;/home/component/.component_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The profile tries to source &lt;code&gt;/home/component/.puma_profile&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This allows our libraries to work in a similar fashion to the &lt;a href=&#34;http://en.wikipedia.org/wiki/Template_method_pattern&#34; target=&#34;_blank&#34;&gt;Template Method Pattern&lt;/a&gt;, where by subsequent inheriting layers can add their own behavior while overriding specific upstream configuration.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As well as the above profile files, each library adds its own additional behaviors. For example, the first library &amp;ldquo;Component Base&amp;rdquo; also sets up the following items:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a &lt;code&gt;component&lt;/code&gt; user account&lt;/li&gt;&#xA;&lt;li&gt;sets up the server instance to utilize our custom logging service&lt;/li&gt;&#xA;&lt;li&gt;defines an &lt;code&gt;/app&lt;/code&gt; directory with all the correct permissions&lt;/li&gt;&#xA;&lt;li&gt;defines an init script that runs a daemon (set via &lt;code&gt;APP_DAEMON&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;APP_DAEMON&lt;/code&gt; can be overridden by an upstream library&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The second library &amp;ldquo;JRuby Application&amp;rdquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;loads the &amp;ldquo;Component Base&amp;rdquo; as a dependency&lt;/li&gt;&#xA;&lt;li&gt;then loads the JRuby binary&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This means a service that utilizes the &amp;ldquo;JRuby Application&amp;rdquo; library can develop an application that is either user-facing (e.g. has an exposed web service) or is an internal application that does data processing. It&amp;rsquo;s up to the developer to decide what they build.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The third library &amp;ldquo;Puma Init&amp;rdquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;loads the &amp;ldquo;JRuby Application&amp;rdquo; as a dependency&lt;/li&gt;&#xA;&lt;li&gt;creates a &lt;code&gt;/home/component/.component_profile&lt;/code&gt; file&lt;/li&gt;&#xA;&lt;li&gt;this adds Puma specific configuration (and overrides &lt;code&gt;APP_DAEMON&lt;/code&gt; to reference Puma)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;http://puma.io/&#34; target=&#34;_blank&#34;&gt;Puma&lt;/a&gt; is a popular multi-threaded Ruby web server&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The following diagram provides a basic visualization of the inherited layers:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/rpm-libraries.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/rpm-libraries.png&#34; alt=&#34;Better Architecture&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each library acts as a layer that builds upon the last and provides specific functionality that extends the overall behavior.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;docker&#34;&gt;Docker&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Chances are you&amp;rsquo;ve already heard the hype around &lt;a href=&#34;http://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt; and containerization by now. The simple fact is, we use Docker because it helps to keep applications small, focused (think &amp;ldquo;Single Responsibility Principle&amp;rdquo;) and most importantly &amp;ldquo;isolated&amp;rdquo; (think &amp;ldquo;decoupling code&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Docker also helps to make installation of specific low-level software much easier, with standardized communication between running containers helping these services to interact.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We use Docker in a variety of different situations:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Continuous Integration (using a standard master/slave set-up and each build job is its own container)&lt;/li&gt;&#xA;&lt;li&gt;Prototyping (super fast to get up and running using new software)&lt;/li&gt;&#xA;&lt;li&gt;Monitoring and Logging solutions&lt;/li&gt;&#xA;&lt;li&gt;Tooling (e.g. &lt;a href=&#34;https://github.com/spurious-io/&#34; target=&#34;_blank&#34;&gt;Spurious&lt;/a&gt; - see the following section - is built using Docker containers)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All that being said: Docker isn&amp;rsquo;t a panacea. It doesn&amp;rsquo;t fit all project requirements and in some cases it&amp;rsquo;s not the right solution at all. As with all things, consider the pros and cons and use where and when appropriate.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tooling&#34;&gt;Tooling&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The tools you utilize during (and post) development can be fundamental to the success of your project. I wont cover all the various tooling solutions we have in place (as there are just far too many), but there is one tool in particular I want to focus on: &lt;a href=&#34;https://github.com/spurious-io/&#34; target=&#34;_blank&#34;&gt;Spurious&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What Spurious offers is a set of AWS services that you can run locally (i.e. without costing you anything).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The AWS services it currently works with (CloudFormation and SNS to follow at some point in the future):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://aws.amazon.com/s3/&#34; target=&#34;_blank&#34;&gt;S3&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://aws.amazon.com/sqs/&#34; target=&#34;_blank&#34;&gt;SQS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://aws.amazon.com/dynamodb/&#34; target=&#34;_blank&#34;&gt;DynamoDB&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://aws.amazon.com/elasticache/&#34; target=&#34;_blank&#34;&gt;ElastiCache&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Currently there are helpers libraries that will configure the AWS SDK to utilise Spurious (making for an almost seamless integration into your application code). These libraries support &lt;a href=&#34;https://github.com/spurious-io/ruby-awssdk-helper/&#34; target=&#34;_blank&#34;&gt;Ruby&lt;/a&gt;, &lt;a href=&#34;https://github.com/Integralist/spurious-clojure-aws-sdk-helper&#34; target=&#34;_blank&#34;&gt;Clojure&lt;/a&gt; and &lt;a href=&#34;https://github.com/spurious-io/js-aws-sdk-helper/&#34; target=&#34;_blank&#34;&gt;JavaScript&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now this by itself is very useful. We can spin up an instance of Spurious on our machine and start writing application code that interacts with a queue (SQS), a record store (DynamoDB) and a data store (S3), along with caching requests (via ElastiCache). But on top of that is the &lt;a href=&#34;https://github.com/spurious-io/browser&#34; target=&#34;_blank&#34;&gt;Spurious Browser&lt;/a&gt; which allows us to peek inside each of these services using a standard web browser. Meaning, rather than having to waste time writing code to filter down a long list of results from S3; I can instead open Spurious Browser and click on a few links to drill down into the content I&amp;rsquo;m interested in and when I find it I can open the content to view it.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Spurious was born from the need to rapidly prototype new features for our Broker/Renderers, but to also avoid the whole deployment process&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s still in development and has some rough edges (there is a rewrite planned, that will change the implementation language from Ruby to Go), but ultimately we&amp;rsquo;ve been using Spurious on quite a few projects now and it has become indepensible. I highly recommend you take a look.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;fp-oop-and-mvc&#34;&gt;FP, OOP and MVC&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So far in this post we&amp;rsquo;ve been discussing top-level system and architectural design, tooling and other associated processes. In this section I want to take it down a level and briefly express my love for Functional Programming (FP), which will require me to make some comparisons to Object-Oriented Programming (OOP).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OOP and FP are two styles of development that have somewhat apposing interests. OOP is focused more around encapsulation of data, whereas FP likes to &lt;em&gt;filter&lt;/em&gt; data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OOP consists of classes and creating objects where data is hidden inside them, but you can manipulate the data from exposed methods. Whereas FP is generally a collection of pure functions that help to enforce &lt;a href=&#34;http://en.wikipedia.org/wiki/Referential_transparency_%28computer_science%29&#34; target=&#34;_blank&#34;&gt;referential transparency&lt;/a&gt;, and data is passed &lt;em&gt;through&lt;/em&gt; these functions, manipulating it as it goes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the big selling points for (most) FP languages is support for immutability. Immutability is a way of distinguishing state, identity and value. From a practical standpoint: if you modify data, then the changes will result in a modified &lt;em&gt;copy&lt;/em&gt; of the original data (as apposed to mutating it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ve seen a recent spurt of interest around immutability (and FP in general) in the JavaScript community as of late (with &lt;a href=&#34;https://swannodette.github.io/mori/&#34; target=&#34;_blank&#34;&gt;Mori.js&lt;/a&gt; and &lt;a href=&#34;https://facebook.github.io/immutable-js/&#34; target=&#34;_blank&#34;&gt;immutable-js&lt;/a&gt; as a couple of examples, but there have been others and they&amp;rsquo;ve been around for much longer). Immutability can help to eradicate a whole host of bugs that can catch you out in a language as mutable as JavaScript (and even more so in languages where code can be multi-threaded).&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Languages like Clojure, for example, also implement persistent data structures, that make immutability easy and inexpensive. I recommend visiting the &lt;a href=&#34;http://clojure.org/&#34; target=&#34;_blank&#34;&gt;Clojure website&lt;/a&gt; and finding out more about the underlying implementation details, as it&amp;rsquo;s quite an interesting read&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Typically you&amp;rsquo;ll find a mixed bag of opinions: some organizations are OOP based, others prefer FP. What&amp;rsquo;s worth being aware of is that this isn&amp;rsquo;t an &amp;ldquo;either or&amp;rdquo; situation. You can find some benefits from having the structural/encapsulation benefits of OOP while implementing certain features in a functional way (but I think that&amp;rsquo;s a topic for another day). The &amp;ldquo;OOP with FP&amp;rdquo; methodology is quite easy with a language like &lt;a href=&#34;http://www.scala-lang.org/&#34; target=&#34;_blank&#34;&gt;Scala&lt;/a&gt; which seamlessly incorporates both styles within their language design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll also find the Clojure programming language (which isn&amp;rsquo;t a strict FP language, although it offers many of the features you&amp;rsquo;ll expect to find), actually incorporates certain OOP principles in both the language API (as it&amp;rsquo;s built on top of the JVM and so it applies some idiomatic lisp syntax to creating Classes and Interfaces) and in some of its popular libraries developed by the open-source community. One example of this is the popular &lt;a href=&#34;https://github.com/stuartsierra/component&#34; target=&#34;_blank&#34;&gt;Component&lt;/a&gt; library that allows for easier management of the lifecycle of software components by encapsulating data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for a discussion around using OOP vs FP is because there are different pros and cons to both styles of development when it comes to high traffic, distributed and concurrent software systems. Although we&amp;rsquo;re primarily an OOP based organization and through good code design have not suffered any ill-effect from using OOP; some members of the team (myself included) have since been exposed to the greater simplicity and reduction of bugs that inherently occurs when utilizing FP and languages that natively support immutability.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Immutability is the key to avoiding complex mutexes and semaphores when writing multi-threaded code. To find out more on the subject please take a read of &lt;a href=&#34;/posts/concurrency/&#34;&gt;&amp;ldquo;Thread Safe Concurrency&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One last point I&amp;rsquo;d like to cover is the (ab)use of the MVC &lt;em&gt;pattern&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First of all, there is no official design pattern called &amp;ldquo;MVC&amp;rdquo; (if anything it could be considered an &amp;ldquo;architectural pattern&amp;rdquo;; but most people seem to refer to it as a design pattern). It is merely a collection of smaller patterns that have commonly been grouped together to form what is known as &amp;ldquo;Model, View, Controller&amp;rdquo; (lest we get caught up discussing the confusion around why so many developers design their software around a single global MVC architecture, as apposed to multiple smaller MVC structures within their applications - but that&amp;rsquo;s probably a discussion for another day).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Regardless of its apparent popularity, MVC isn&amp;rsquo;t always the right tool for the job. It&amp;rsquo;s worth being vigilant and recognising when you&amp;rsquo;re about to cargo-cult a particular technology or design pattern, because in a lot of cases MVC can actually be seen as overkill and add additional complexity and complication to your code that you don&amp;rsquo;t need. Let&amp;rsquo;s be clear here: MVC may well be the right choice for you; but I would urge you to investigate the merits of using it against an alternative set of patterns first that could help you simplify your software design (for example, a simple observer pattern can suffice for many applications; build up the layers of complexity as they&amp;rsquo;re needed - don&amp;rsquo;t go and jump straight in with an MVC framework).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The (ab)use of MVC has also become standard fare within the realm of front-end JavaScript libraries. Again, I&amp;rsquo;m not saying MVC is bad or wrong; but what I am saying is &amp;ldquo;do you need it?&amp;rdquo;. Remember to consider what it is you&amp;rsquo;re signing up to when you utilise a particular open-source (or even commercial) library within your application. Simplicity is the key.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;inherent-complexity&#34;&gt;Inherent complexity&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are some pieces of software and tools that are inherently complex by design. As an example, I want to demonstrate this by taking a look at our application deployment pipeline, which utilizes &lt;a href=&#34;http://jenkins-ci.org/&#34; target=&#34;_blank&#34;&gt;Jenkins&lt;/a&gt; and provides us with a full circle continuous deployment process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The process can (roughly) be broken down into the following steps:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Merge code into our version control system &lt;a href=&#34;https://www.github.com/&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;A webhook is set-up for our repository that alerts Jenkins&lt;/li&gt;&#xA;&lt;li&gt;Jenkins starts building our first job (pulls codes and installs dependencies)&lt;/li&gt;&#xA;&lt;li&gt;If that job passes, our job is configured to call another Jenkins job&lt;/li&gt;&#xA;&lt;li&gt;The next job runs our unit tests, and when they pass it again calls another job&lt;/li&gt;&#xA;&lt;li&gt;The next job builds and deploys our application to our integration server&lt;/li&gt;&#xA;&lt;li&gt;If the deploy is successful we call another job that runs our integration tests&lt;/li&gt;&#xA;&lt;li&gt;If the tests fail, then we mark the job as failed&lt;/li&gt;&#xA;&lt;li&gt;If the tests pass, then we trigger the next job which deploys to our test server&lt;/li&gt;&#xA;&lt;li&gt;Once deployed to test we again run integration tests and mark the deploy as either successful or failed&lt;/li&gt;&#xA;&lt;li&gt;If we&amp;rsquo;re good up until this point, then we will deploy to live&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now, even breaking down this process into individual (simplified) steps, I&amp;rsquo;m sure you can appreciate that this deployment process will look fairly complicated in practice; and it is. We&amp;rsquo;ve got multiple jobs that have been abstracted to a level where we can re-use them across multiple different projects, but this process of abstraction makes understanding what&amp;rsquo;s happening quite complicated because you have to context switch between Jenkins and GitHub.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One method of abstraction we used was to take advantage of IoC (inversion of control). In our jobs - to help us keep a record of changes to the build scripts - we decided the best thing to do was to pull down &lt;a href=&#34;http://en.wikipedia.org/wiki/Bash_%28Unix_shell%29&#34; target=&#34;_blank&#34;&gt;bash&lt;/a&gt; scripts from GitHub and execute them to implement specific functionality that had been abstracted away behind a reusable function. This is what allows us to create generic jobs that can be reused across many different projects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This happened because we tried to approach our build jobs the same way we would application code; and although we have a nice DRY set of build jobs, it&amp;rsquo;s a difficult thread to follow (especially when there is an error within a section of your deployment pipeline - it can become quite hard to locate and debug).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is one of the primary reasons we feel our current solution is &amp;ldquo;complicated&amp;rdquo;. It&amp;rsquo;s because Jenkins wasn&amp;rsquo;t designed with this type of complex workflow in mind, and so although there are plugins that can help visualize and construct full deployment pipelines, they&amp;rsquo;re not ideal. I wont go into the details of why, as that&amp;rsquo;s a little outside the scope of this article, but trust me: it&amp;rsquo;s a bit of a hack to get continuous delivery pipelines working really smoothly in Jenkins.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In a bid to simplify our deployment pipeline we have planned to take the following approach to resolve our issues with Jenkins (note this approach might not work for you, and dependent on your team, your mileage may vary):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Reduce our multiple connected generic jobs down into a single job; meaning we&amp;rsquo;ll manually pass in the environment we wish the component to be deployed to, every time the job is run (this is a temporary measure, as it gives us a sane baseline from which we can build upon)&lt;/li&gt;&#xA;&lt;li&gt;We will then investigate alternative methods for making Jenkins work with complex deployment pipelines (such as &lt;a href=&#34;https://wiki.jenkins-ci.org/display/JENKINS/Template+Project+Plugin&#34; target=&#34;_blank&#34;&gt;Jenkin Templates&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Then, when we get capacity within the team, we&amp;rsquo;ll look to set-up &lt;a href=&#34;http://www.go.cd/&#34; target=&#34;_blank&#34;&gt;GOCD&lt;/a&gt; which we set-up as a tech spike previously and found it worked very well with our team&amp;rsquo;s workflow.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;containerization&#34;&gt;Containerization&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As of &lt;sup&gt;2014&lt;/sup&gt;&amp;frasl;&lt;sub&gt;2015&lt;/sub&gt; the tech world is buzzing about &lt;a href=&#34;https://www.docker.com/&#34; target=&#34;_blank&#34;&gt;Docker&lt;/a&gt;. If you want to find out more about what Docker is and how it works then I recommend going through their website as it has a wealth of good information. But in summary: a docker &amp;ldquo;container&amp;rdquo; is an isolated set of processes that can be connected with other &amp;ldquo;containers&amp;rdquo; to create different types of software applications, but in a more manageable way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of Docker&amp;rsquo;s biggest selling points is the mantra: &amp;ldquo;build once, run anywhere&amp;rdquo;. This means you can define your requirements and be confident that it&amp;rsquo;ll run the same, whether your platform is AWS ECS, Google Cloud Compute or Tutum.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A simple example usually given to demonstrate how Docker might be used in a traditional web development workflow is: create a Docker container that runs your web app, then create another container that runs your database and in another container you might have a caching service (e.g. Redis or Memcache). All of these containers can be linked together by Docker so they can communicate safely with each other while providing decoupled isolation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This description doesn&amp;rsquo;t do justice to what Docker can offer though and if you&amp;rsquo;ve not played around with it yet then I strongly urge you to try it out. To give you some ideas, I&amp;rsquo;ve listed below a few different ways we utilize Docker, and raise some small points about with using it as well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some use cases we apply Docker to:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Continuous Delivery (each Jenkins job is a fresh container, with an isolated set of dependencies - this allows us to avoid the issue of developer&amp;rsquo;s wanting to upgrade specific software versions and being told they can&amp;rsquo;t because an updated version will cause issue for other products)&lt;/li&gt;&#xA;&lt;li&gt;Dynamically building sandboxes at runtime which host specific GitHub branches (for sharing with stake holders)&lt;/li&gt;&#xA;&lt;li&gt;Tech spikes (Docker allows us to focus on features and not get caught up with installation/configuration issues)&lt;/li&gt;&#xA;&lt;li&gt;Helping us to better structure and develop software (&lt;a href=&#34;https://github.com/spurious-io/&#34; target=&#34;_blank&#34;&gt;Spurious&lt;/a&gt; uses Docker to run each of the faked AWS services)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Containerizing your applications will likely become the standard software architecture design pattern in the very near future, so it&amp;rsquo;s worth your time playing around and getting to grips with the tools available, and how best to break down your potential monolith into decoupled microservices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But with that said, what are the current pain points for containerizing all your software? Are there times when you wouldn&amp;rsquo;t want to use it? Well, there are a couple of things worth considering:&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;tooling-1&#34;&gt;Tooling&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The tooling available to debug containers is still considered to be quite immature. Docker does offer both a &lt;code&gt;log&lt;/code&gt; command as well as an &lt;code&gt;exec&lt;/code&gt; command (which lets you jump into a running container using a bash shell); but there can be instances where neither of those options will yield success.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, a container wasn&amp;rsquo;t logging any thing, and on top of that the application (which when run outside of the container, would run forever in an infinite loop) would run initially and then stop when run inside the container, and so the &lt;code&gt;exec&lt;/code&gt; command was not an option as I couldn&amp;rsquo;t jump inside a container that was no longer running.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the latest binary Docker has provided additional stats that are exposed via the &lt;a href=&#34;https://docs.docker.com/reference/commandline/cli/#stats&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;docker stats {container}&lt;/code&gt;&lt;/a&gt; command&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;scaling&#34;&gt;Scaling&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Scaling containers requires a new approach that might not fit your current infrastructure model. Also, the question of scalability could potentially be simplified by the upcoming release of Docker&amp;rsquo;s &amp;ldquo;Swarm&amp;rdquo; feature; which offers the ability to control a cluster of machines running Docker via a single endpoint. But how easily this makes actually &lt;em&gt;scaling&lt;/em&gt; a cluster of running docker instances within a single host, remains to be seen in practice.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Traditional &amp;ldquo;vertical vs horizontal&amp;rdquo; scaling is quite straight forward: with vertical scaling you increase the size of the box running your application; whereas with horizontal scaling you increase the number of boxes instead. The ability to horizontally scale a cluster of docker containers might not be so straight forward.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine I have an EC2 server instance running with an &lt;a href=&#34;http://aws.amazon.com/autoscaling/&#34; target=&#34;_blank&#34;&gt;auto scaling group&lt;/a&gt; that creates a new server instance when the CPU reaches 70%. On this instance I have a web service running inside a Docker container and it&amp;rsquo;s maxing out its resources. We&amp;rsquo;d have to use custom metrics fired off from our Docker container to &lt;a href=&#34;http://aws.amazon.com/cloudwatch/&#34; target=&#34;_blank&#34;&gt;AWS CloudWatch&lt;/a&gt;, which would allow us to define an alarm that triggered a new server instance to be created. Otherwise our ASG wouldn&amp;rsquo;t catch the Docker container failing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Docker Swarm, &lt;em&gt;could&lt;/em&gt; help here (it&amp;rsquo;s not released yet and we&amp;rsquo;ve not had a chance to try an early pre-release)? But it appears to only work by having a pre-created pool of servers, rather than dynamically generated server instances. Maybe once we see an official release and get the opportunity to see it in action we&amp;rsquo;ll find it handles the issue of scaling perfectly. But until then, it&amp;rsquo;s just something to consider before going too far ahead with designing your infrastructure around Docker.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;orchestration&#34;&gt;Orchestration&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Running Docker containers can result in very long commands that are difficult to visually parse and take a long time to retype. This is the primary problem orchestration tools such as (the soon-to-be released) &lt;a href=&#34;https://blog.docker.com/2014/12/docker-announces-orchestration-for-multi-container-distributed-apps/&#34; target=&#34;_blank&#34;&gt;Docker Compose&lt;/a&gt; are aiming to solve. I&amp;rsquo;ve used an early release of Docker Compose and it seems promising. It definitely helps to document the infrastructure set-up (much like AWS CloudFormation does) and allow for easily reproducible environments.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;layers&#34;&gt;Layers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is actually quite a specific concern, and one that might not really have any practical basis or realistic solution (from an implementation point of view, or because there are already work arounds); but I&amp;rsquo;ve found building images that need to utilise private security authentication credentials to be more awkward than it feels like it should be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When building a Docker image, you&amp;rsquo;re constructing it from multiple layers (this allows Docker to create an image using cached layers and greatly improving the build performance), but this means if you add your security credentials then they&amp;rsquo;ll be baked into the resulting image. I would prefer it if it was possible to remove layers so that you could add the credentials, pull down further resources within the Docker image and then remove the layer that included your credentials.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The work around to this is to build a new image from an already running container which has already mounted your credentials. Now there is nothing necessarily wrong with this approach, it just doesn&amp;rsquo;t feel very clean either. I may be complaining about nothing, but it&amp;rsquo;s something that&amp;rsquo;s stuck with me. I&amp;rsquo;d be interested to know how other organizations and developers are handling building images with private authentication.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An alternative suggestion from &lt;a href=&#34;https://twitter.com/stevenjack85&#34; target=&#34;_blank&#34;&gt;Steven Jack&lt;/a&gt; was that maybe Docker could add build time environment variables. These would allow you to provide your security credentials at the point of building your image rather than having them baked inside of the image. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;docker build -t some/image -e MY_SECRET=KEY&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;optimizing-user-experience&#34;&gt;Optimizing user experience&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I said at the start of this post that I wouldn&amp;rsquo;t be covering very much front-end technologies because they were vast, complex and the recommended patterns seem to change on a regular basis. But this isn&amp;rsquo;t to say there aren&amp;rsquo;t things you should be doing when designing your user facing applications. Below is a short list of topics that you should spend some time investigating:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Performance: since 2007 &lt;a href=&#34;http://stevesouders.com/&#34; target=&#34;_blank&#34;&gt;Steve Souders&lt;/a&gt; has been the godfather of front-end performance. Read his books and his blog posts. You&amp;rsquo;ll see a massive improvement from following his best practices (which are pretty much industry standard nowadays).&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://facebook.github.io/react/&#34; target=&#34;_blank&#34;&gt;React&lt;/a&gt; is a &amp;ldquo;JavaScript library for building user interfaces&amp;rdquo;. I wont go into the details of the library here, but suffice to say it offers a lot of interesting features, such as implementing a Virtual DOM for high performance; no templates for building interfaces and avoiding two-way data binding in favor of &amp;ldquo;reconciliation diffing&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;Immutability: this is a tenet of Functional Programming and is finally starting to see a rise within the JavaScript community. There are a few different libraries available to support immutable data, such as &lt;a href=&#34;http://facebook.github.io/immutable-js/&#34; target=&#34;_blank&#34;&gt;immutable-js&lt;/a&gt; and &lt;a href=&#34;http://swannodette.github.io/mori/&#34; target=&#34;_blank&#34;&gt;Mori&lt;/a&gt;. I would recommend trying out these libraries, as immutability can help to reduce a whole host of hard to reason about bugs.&lt;/li&gt;&#xA;&lt;li&gt;BEM: Block Element Modifier is a predescribed notation for writing CSS that allows it to reduce complexity/specificity, while increasing maintainability and reusability. &lt;a href=&#34;http://csswizardry.com/&#34; target=&#34;_blank&#34;&gt;Harry Roberts&lt;/a&gt; has written extensively about it; and in fact I would recommend reading anything he has to say on the subject of CSS and how to write it to support large scale applications.&lt;/li&gt;&#xA;&lt;li&gt;RWD: Responsive Web Design is neither new or an easy topic. There is a myriad of techniques for implementing RWD properly and in a progressively enhanced/performant fashion. I would recommend reading anything &lt;a href=&#34;http://bradfrost.com/&#34; target=&#34;_blank&#34;&gt;Brad Frost&lt;/a&gt; has to say. See his &lt;a href=&#34;http://www.pattern-lab.info/&#34; target=&#34;_blank&#34;&gt;Pattern Library&lt;/a&gt; for lots of good code examples.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;where-have-we-succeeded-failed&#34;&gt;Where have we succeeded/failed?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Admitting failure is never easy, and so you don&amp;rsquo;t often see blog posts describing how some new feature or technology didn&amp;rsquo;t quite work out as planned. I&amp;rsquo;m personally of the opinion that recognizing situations where we&amp;rsquo;ve failed (and aiming to &amp;ldquo;fail fast&amp;rdquo;) is a healthy way to react. Much like in the world of distributed computing, you have to accept the fact that services are going to fail and instead focus on improving the situation if it were to arise.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this in mind, I can say that our current deployment pipeline (using Jenkins) hasn&amp;rsquo;t worked out that well for us (as described earlier in this post). It&amp;rsquo;s a bit convoluted and definitely feels too complicated to be used for much longer. Making changes to our deployment process is not easy, and can take quite some time for an engineer to build up a mental model of the pipeline in their head. We shouldn&amp;rsquo;t have to be following a thread in the manner we do at the moment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, although we mark a release as failed if any of the unit/integration tests fail; we still have to manually revert the release which is not good at all. It&amp;rsquo;s hard to explain why this hasn&amp;rsquo;t been solved yet, without getting lost in technical details that are very specific to our infrastructure. This is a problem we are still very keen to resolve in order for us to get a true CD experience in place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With that being said, we&amp;rsquo;re aware of this problem and are pro-actively looking to resolve the problem by following these steps:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Simplify the problem (get a baseline that works)&lt;/li&gt;&#xA;&lt;li&gt;Carry out a technical spike for GOCD (understand if it&amp;rsquo;ll fit our needs)&lt;/li&gt;&#xA;&lt;li&gt;Implement new solution based upon results of technical spike (i.e. GOCD or Jenkins Template)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Continuous Delivery can be a hard problem to solve in a non-complicated manner. So you have to be practical with the approach for finding a solution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Something else I&amp;rsquo;ve realized, is that we&amp;rsquo;re slowly cargo-culting our &lt;a href=&#34;https://github.com/BBC-News/alephant&#34; target=&#34;_blank&#34;&gt;Alephant framework&lt;/a&gt;. By that I mean: we&amp;rsquo;re finding ever more ways of fitting the framework to suit the project rather than designing a solution around the problem space. This should not happen. Each project has a unique set of requirements that need to be considered; and if the problem can be solved nicely and efficiently using the pre-described &amp;ldquo;broker/renderer&amp;rdquo; pattern the Alephant Framework implements, then great. But we shouldn&amp;rsquo;t feel required to use it&amp;hellip; you know, just because.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With regards to our abstracted RPM libraries: even though we&amp;rsquo;ve separated certain related functionality into individual libraries, we could still extract certain configuration into their own isolated libraries. For example, our &amp;ldquo;Component Base&amp;rdquo; includes setting up logging on a server instance, as well as defining app specific configuration. Some of our components literally only need logging provided &amp;ldquo;out of the box&amp;rdquo; and nothing else; so extracting this into a logging library means those components can require it as a dependency while also allowing &amp;ldquo;Component Base&amp;rdquo; to consume it as well. This gives us even more flexibility and granularity of control.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we originally were building our monitoring solution we were able to prototype it really quickly using Docker. We had containers linked together that were using &lt;a href=&#34;http://graphite.wikidot.com/&#34; target=&#34;_blank&#34;&gt;Graphite&lt;/a&gt; and &lt;a href=&#34;http://grafana.org/&#34; target=&#34;_blank&#34;&gt;Grafana&lt;/a&gt;, but we soon realized this set-up wouldn&amp;rsquo;t scale when along came Chaos Monkey and wiped out our instance in one hit. We needed these services to be decoupled to improve the resiliency. This was an instance where Docker wasn&amp;rsquo;t necessarily the best tool for the job. This helped us to improve our solution by changing to use &lt;a href=&#34;http://influxdb.com/&#34; target=&#34;_blank&#34;&gt;InfluxDB&lt;/a&gt; instead and thus reduced the moving parts (as Graphite is actually made up of three separate applications: Whisper, Carbon and Graphite-web). We were then able to run InfluxDB and Grafana as separate services using traditional applications rather than Docker.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In some places we&amp;rsquo;ve succeeded by catching ourselves trying to over engineer specific solutions. As an example, we recently had a need to archive some components that our Alephant Framework was used to render. We needed to move the rendered components from one S3 bucket to another S3 bucket. This archiving process would only happen once (after the event the components were associated with - so this wasn&amp;rsquo;t a service that needed to run &lt;sup&gt;24&lt;/sup&gt;&amp;frasl;&lt;sub&gt;7&lt;/sub&gt;). We initially started setting up an EC2 server and all that goes along with deploying it via our own infrastructure (which is an abstraction on top of AWS), only to find that really the best solution was to utilize the new (as of 2015) &lt;a href=&#34;http://aws.amazon.com/lambda/&#34; target=&#34;_blank&#34;&gt;AWS Lambda&lt;/a&gt; service; which was built specifically for these isolated event based scenarios. It helped to simplify the solution itself as well as reduce overall costs. Plus we had the opportunity to play around with some new technology; which is always fun :-)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So here we are finally at the end of my whirlwind tour of software design and tooling. We&amp;rsquo;ve covered mainly back-end/dev-ops related technologies and ever so briefly considered some pointers for the front-end.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s difficult to reduce many many years of front-end and back-end experience into a single blog post. You may as well write a book (or two, or three) instead. The idea behind this post was to provide a taster for what the current thought process is with regards to our entire tech stack as of 2015. Some of these ideas will become standard practice, others will quietly fade away. But we must always be open to change and experimentation and finding ways to simplify our processes rather than over engineering them and promoting unnecessary complexity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I hope some of what you&amp;rsquo;ve read here was enlightening. Feel free to get in contact with me via GitHub or Twitter using the handle &amp;ldquo;integralist&amp;rdquo;.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/designing-for-simplicity/</guid>
      <link>https://www.integralist.co.uk/posts/designing-for-simplicity/</link>
      <pubDate>Mon, 30 Mar 2015 00:00:00 +0000</pubDate>
      <title>Designing for Simplicity</title>
    </item>
    <item>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;2020.02.25 UPDATE&lt;/strong&gt;: this post was written a long time ago and I realize now (upon reflection) that it dips hazardously in-and-out between various programming languages without really warning the user properly ahead of time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reason for using different languages was to highlight the fact that the various concurrency tools and mechanisms weren&amp;rsquo;t fully supported across languages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Feel free to skip over these code examples if you like. The explanations that precede the examples should hopefully suffice.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Concurrency is a difficult concept. Regardless of programming language or idiom that you use, the practice of programming a &amp;ldquo;thread-safe&amp;rdquo; application can be harder than you think.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are two fundamental models of concurrency:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Shared Memory&lt;/li&gt;&#xA;&lt;li&gt;Message Passing&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;In the first, we have concepts such as Threads, Locks and Mutexes. In the latter we have patterns such as Actors and CSP, which rely on the mantra of&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;don&amp;rsquo;t communicate by sharing memory; share memory by communicating&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;shared-memory&#34;&gt;Shared Memory&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following diagram is an extremely simplistic view of how CPUs, Processes and Threads interact but should help us to better understand why code can become &lt;strong&gt;NON&lt;/strong&gt; thread-safe (as far as the &amp;ldquo;Shared Memory&amp;rdquo; model is concerned; we&amp;rsquo;ll see shortly that the &amp;ldquo;message passing&amp;rdquo; model side steps this issue):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/cpu-processes-and-threads.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/cpu-processes-and-threads.png&#34; alt=&#34;cpu processes and threads&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;for those of you who cannot see the image, effectively a process can spawn multiple threads and each thread belonging to a specific process shares the memory related to the process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning if your software process creates two threads, then both threads have access to the same memory space and thus can manipulate the same chunk of memory (and by memory, I&amp;rsquo;m specifically referring to data the application creates/has access to).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means, if your software creates some mutable data (e.g. in Ruby this could look something like &lt;code&gt;foo = &amp;quot;bar&amp;quot;&lt;/code&gt; - a &lt;code&gt;foo&lt;/code&gt; variable that holds the String value &lt;code&gt;bar&lt;/code&gt;) and you want to modify the value of the variable, then multiple threads could manipulate the value in an unexpected order and subsequently cause a difficult to locate bug.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Any time you create a new Thread and within that Thread you modify a mutable piece of data you should be concerned about how &amp;ldquo;thread-safe&amp;rdquo; that data is.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you&amp;rsquo;re also utilising immutable data structures (as found in more functional languages, but also languages such as Go where they &amp;ldquo;pass by value&amp;rdquo; rather than &amp;ldquo;pass by reference&amp;rdquo;) then this also makes code less prone to thread-safety concerns (but that&amp;rsquo;s a discussion for another day)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;message-passing&#34;&gt;Message Passing&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The message passing model relies on no data being shared, but rather communication between processes happening via either a message bus or by piping messages down a channel (depending on which style is implemented in your programming language of choice).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As well as avoiding the issue of data being shared, it also avoids the issue of trying to recover from failures (which thread/process is the correct one); which is a hard problem to reason about.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;various-options&#34;&gt;Various options&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are four main types of solutions to the problem of thread-safe concurrency:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Mutexes/Semaphores&lt;/li&gt;&#xA;&lt;li&gt;Software Transactional Memory (STM)&lt;/li&gt;&#xA;&lt;li&gt;The &amp;ldquo;Actors&amp;rdquo; pattern&lt;/li&gt;&#xA;&lt;li&gt;Communicating Sequential Processes (CSP)&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s investigate each of these in turn:&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mutexes-semaphores&#34;&gt;Mutexes/Semaphores&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;ll be discussing specifically &amp;ldquo;mutexes&amp;rdquo; rather than &amp;ldquo;semaphores&amp;rdquo; (they have very similar purposes - in that they control access to specific data - although a mutex offers some additional guarantees).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When using a mutex, you can &amp;ldquo;lock&amp;rdquo; a piece of data so only that specific Thread has access to the data. When done manipulating the data you can &amp;ldquo;unlock&amp;rdquo; it, thus allowing another Thread to use a mutex to &amp;ldquo;lock&amp;rdquo; the data so it can make its own changes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at an example (in Ruby):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# imagine `data` is some shared state&#xA;&#xA;def update&#xA;  mutex = Mutex.new&#xA;&#xA;  Thread.new { mutex.synchronize { data += 1} }.join&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;for the full Mutex API see &lt;a href=&#34;http://www.ruby-doc.org/core-2.1.5/Mutex.html&#34; target=&#34;_blank&#34;&gt;http://www.ruby-doc.org/core-2.1.5/Mutex.html&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;This particular solution is the simplest of the three. BUT it doesn&amp;rsquo;t take into account any logic for handling unexpected changes to data (we&amp;rsquo;ll see what that means later on in the &lt;a href=&#34;#6&#34;&gt;STM&lt;/a&gt; section).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;mutex-vs-semaphore&#34;&gt;Mutex vs Semaphore?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A semaphore is a construct which can be used to &lt;em&gt;constrain&lt;/em&gt; or &lt;em&gt;control&lt;/em&gt; access to a shared resource (typically this means access across multiple threads). Think of a semaphore as a more &amp;lsquo;generalized&amp;rsquo; version of a mutex.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A mutex ensures a single thread only ever has access to a segment of your code (e.g. it guards the &amp;lsquo;critical section&amp;rsquo; of a piece of code), where as a semaphore is concerned with ensuring that at &lt;em&gt;most&lt;/em&gt; N threads can access your code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below is an example in golang:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Package middleware provides wrapper functions around the http.Handler&#xA;// interface, allowing for an incoming HTTP request to be modified or analysed.&#xA;package middleware&#xA;&#xA;import (&#xA;    &amp;quot;net/http&amp;quot;&#xA;&#xA;    &amp;quot;github.com/example/internal/pkg/settings&amp;quot;&#xA;    &amp;quot;golang.org/x/sync/semaphore&amp;quot;&#xA;)&#xA;&#xA;// LimitConcurrency will reject any new connections that exceed the service&#39;s&#xA;// ability to continue functioning.&#xA;func LimitConcurrency(handler http.Handler, config *settings.Config) http.Handler {&#xA;      s := semaphore.NewWeighted(int64(config.ConcurrencyLimit))&#xA;&#xA;    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        if !s.TryAcquire(1) {&#xA;            http.Error(w, &amp;quot;TOO_MANY_CONCURRENT_CONNECTIONS&amp;quot;, http.StatusServiceUnavailable)&#xA;            return&#xA;        }&#xA;        defer func() {&#xA;            s.Release(1)&#xA;        }()&#xA;&#xA;        handler.ServeHTTP(w, r)&#xA;    })&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how we have a similar API to a mutex (e.g. with a mutex you have to acquire a &amp;lsquo;lock&amp;rsquo; where as with a semaphore you have a number of &amp;lsquo;spaces&amp;rsquo; the code is allowed to acquire). We attempt to &amp;lsquo;acquire&amp;rsquo; one of the available semaphore spaces (e.g. when we created the semaphore we passed in a threshold of &lt;code&gt;config.ConcurrencyLimit&lt;/code&gt; which could be set to a value of &lt;code&gt;100&lt;/code&gt;). In the case of the threshold being &lt;code&gt;100&lt;/code&gt; it means we have &lt;code&gt;100&lt;/code&gt; semaphore &amp;lsquo;spaces&amp;rsquo; available before our code starts to reject incoming connections.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;atomic-operations&#34;&gt;Atomic operations&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Locks and mutexes allow operations to become &lt;em&gt;atomic&lt;/em&gt;, meaning that the change happens &amp;ldquo;as a whole&amp;rdquo;. Meaning it becomes thread safe because another thread can&amp;rsquo;t accidentally read a piece of data/state/memory that is half done (e.g. &lt;code&gt;+=&lt;/code&gt; in the above Ruby example would not be thread safe without the Mutex because a thread could read the value of &lt;code&gt;data&lt;/code&gt; inbetween the read and the assignment that &lt;code&gt;+=&lt;/code&gt; carries out).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;stm&#34;&gt;STM&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Software Transactional Memory is known as being an &amp;ldquo;optimistic&amp;rdquo; process. Compare this to the lock-synchronisation mechanism of a Mutex, which implies the onus of whether a write action will succeed, should be on the &amp;ldquo;writer&amp;rdquo; (i.e. the &amp;ldquo;writer&amp;rdquo; locks the data, writes the data, then releases the lock).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The STM on the other hand doesn&amp;rsquo;t care what happens in another Thread, it instead records all the changes in a log file and then just before it confirms the write (referred to as a &amp;ldquo;commit&amp;rdquo; in STM terminology) it verifies the data we&amp;rsquo;re modifying hasn&amp;rsquo;t changed, and if it hasn&amp;rsquo;t we go ahead and commit the change made by our Thread.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a change has been made to the shared data source, then the transation will start over; but this time using the latest copy of the data we&amp;rsquo;re modifying (this can in some cases cause a deadlock to occur).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Because the STM retries transactions when they fail, we should ensure that code within a transaction is idempotent and side effect free. Otherwise if the code isn&amp;rsquo;t idempotent, then that code will be run again and might mean data is changed or recorded in ways you didn&amp;rsquo;t expect (e.g. a call to log some data within a transaction could be called multiple times!)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the STM is best used for applications that have frequent reads and can allow for low to medium write collisions. If you expect lots of write collisions then it may be best to opt for another pattern, such as the &lt;a href=&#34;#7&#34;&gt;Actors&lt;/a&gt; pattern discussed in the following section.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the Clojure programming language you&amp;rsquo;ll also find that the STM facilitates &amp;ldquo;embedded transactions&amp;rdquo;, which allows for greater atomicity. What this means in pratice, is that if there is a transaction that contains a sub-transaction, then in some implementations of the STM a failed transaction won&amp;rsquo;t necessarily cause the sub-transaction to fail. But in Clojure it will. Meaning that it&amp;rsquo;s definitely an atomic operation (all or nothing).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;clojure-example&#34;&gt;Clojure example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following example uses the Clojure programming language to implement a thead-safe modification via the STM (specifically the &lt;code&gt;ensure&lt;/code&gt; function allows us to tell the STM what shared memory to watch for changes while our transaction is ongoing).&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;h4 id=&#34;quick-clojure-concurrency-detour&#34;&gt;Quick Clojure Concurrency Detour&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;A quick detour before continuing onto the example code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clojure provides quite a few different mechanisms and functions for handling concurrency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The three core mechanisms are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;atom&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;agent&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A &lt;code&gt;ref&lt;/code&gt; provides synchronised access to shared mutable state in a &lt;em&gt;coordinated&lt;/em&gt; fashion (i.e. it uses the STM to ensure multiple references are coordinated before applying changes). Whereas an &lt;code&gt;atom&lt;/code&gt; is similiar, but differs in that it works like a straight forward CAS (compare and swap) operation. So an &lt;code&gt;atom&lt;/code&gt; is considered &lt;em&gt;un-coordinated&lt;/em&gt;. An &lt;code&gt;agent&lt;/code&gt; is the same as an &lt;code&gt;atom&lt;/code&gt; with the exception that it can be run asynchronously.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clojure&amp;rsquo;s atom provides a validator function (pass &lt;code&gt;:validator&lt;/code&gt; argument followed by a validating function), which prevents invalid values being set; similar to a function&amp;rsquo;s pre/post assertion conditions. You are also able to &amp;ldquo;watch&amp;rdquo; atoms for state changes via &lt;code&gt;add-watch&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;there is also &lt;code&gt;Var&lt;/code&gt; type which is a mutable variable and is created via the &lt;code&gt;def&lt;/code&gt; form. A variable is &amp;ldquo;thread-local&amp;rdquo; meaning it isn&amp;rsquo;t shared across threads (whereas &lt;code&gt;atom&lt;/code&gt;, &lt;code&gt;agent&lt;/code&gt; and &lt;code&gt;ref&lt;/code&gt; are all accessible across threads)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s consider the following functions:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ref-set&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;alter&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ensure&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;commute&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All of these functions &lt;em&gt;must&lt;/em&gt; be called from within a transaction (e.g. this is achieved by calling them from within a &lt;code&gt;dosync&lt;/code&gt; block).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first function &lt;code&gt;ref-set&lt;/code&gt; allows you to change the value of a reference directly (i.e. specifying a value rather than using a function).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second function &lt;code&gt;alter&lt;/code&gt; applies a user specified function to the reference. The transaction itself will be retried if any reference written to within the transaction has changed outside of that transaction.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The third function &lt;code&gt;ensure&lt;/code&gt; helps to resolve a problem that arises when using &lt;code&gt;alter&lt;/code&gt;. The &lt;code&gt;alter&lt;/code&gt; function only retries the transaction when references are written to; this means it doesn&amp;rsquo;t check references that are used within the transaction and &lt;em&gt;haven&amp;rsquo;t&lt;/em&gt; been written to. We can work around this issue and ensure (no pun intended) that any reference used within the transaction - written to or just read - would cause the transaction to restart.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The fourth function &lt;code&gt;commute&lt;/code&gt; increases concurrency for references that you want to monitor for changes but don&amp;rsquo;t really care for their consistency; when you&amp;rsquo;re really only interested in getting the latest value. It helps to increase the concurrency by running the function applied to &lt;code&gt;commute&lt;/code&gt; at least twice (maybe more). This means if you have multiple threads running transactions then whichever transaction changes the value at the point of a commit wins (i.e. last-one-in-wins behavior).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, with that out of the way let&amp;rsquo;s now review the example code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;hr&gt;&#xA;&#xA;&lt;p&gt;The requirement in the code is that the two bank accounts must have at least 1000 in total between them. If we try to remove an amount from either account which results in the total amount falling below 1000 then we should not complete that transaction:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(def current-account (ref 500))&#xA;(def savings-account (ref 600))&#xA;&#xA;(defn withdraw [from constraint amount]&#xA;  (dosync&#xA;    (let [total (+ @from (ensure constraint))]&#xA;      (Thread/sleep 1000) ; allows for a more visible context switch&#xA;      (if (&amp;gt;= (- total amount) 1000)&#xA;        (alter from - amount)&#xA;        (println &amp;quot;Sorry, can&#39;t withdraw due to constraint violation&amp;quot;)))))&#xA;&#xA;(println &amp;quot;STATE BEFORE MODIFYING&amp;quot;)&#xA;(println &amp;quot;Current Account balance is&amp;quot; @current-account)&#xA;(println &amp;quot;Savings Account balance is&amp;quot; @savings-account)&#xA;(println &amp;quot;Total balance is&amp;quot; (+ @current-account @savings-account))&#xA;&#xA;(future (withdraw current-account savings-account 100))&#xA;(future (withdraw savings-account current-account 100))&#xA;&#xA;(Thread/sleep 4000)&#xA;&#xA;(println &amp;quot;STATE AFTER MODIFYING&amp;quot;)&#xA;(println &amp;quot;Current Account balance is&amp;quot; @current-account)&#xA;(println &amp;quot;Savings Account balance is&amp;quot; @savings-account)&#xA;(println &amp;quot;Total balance is&amp;quot; (+ @current-account @savings-account))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the above code could look like the following (but refer to the below note which explains why in some instances, because the transaction can fail and automatically retry, you could possibly see the failure message informing the user that the transaction failed even when it was successful):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;STATE BEFORE MODIFYING&#xA;Current Account balance is 500&#xA;Savings Account balance is 600&#xA;Total balance is 1100&#xA;&#xA;STATE AFTER MODIFYING&#xA;Current Account balance is 500&#xA;Savings Account balance is 500&#xA;Total balance is 1000&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;&lt;code&gt;println&lt;/code&gt; is sending data to &lt;em&gt;stdout&lt;/em&gt; (defined as a thread-local dynamic variable). This variable is binded to the current Thread by default (meaning values don&amp;rsquo;t cross over into other Threads).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A &lt;code&gt;future&lt;/code&gt; creates a new Thread, but the binding of &lt;em&gt;stdout&lt;/em&gt; is inherited by the &lt;code&gt;future&lt;/code&gt;&amp;rsquo;s parent process (i.e. any &lt;code&gt;println&lt;/code&gt; calls within the &lt;code&gt;withdraw&lt;/code&gt; function - which runs in the parent process - can appear in the &lt;code&gt;future&lt;/code&gt;&amp;rsquo;s thread); meaning the output sent by &lt;code&gt;println&lt;/code&gt; doesn&amp;rsquo;t necessarily reflect the correct state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, even when the transaction completes successfully, you might see the failure message printed - at some point in &lt;em&gt;stdout&lt;/em&gt; - because the failing message is coming from an earlier transaction that indeed failed. But after a retry the transaction passed and so the message you see in &lt;em&gt;stdout&lt;/em&gt; doesn&amp;rsquo;t reflect the latest status of the application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would suggest that the &lt;code&gt;println&lt;/code&gt; message be moved outside of the transaction and that you add additional logic after the transaction code (this means after the transaction has completed; inc. retries) as a way to work around this issue with printing messages to &lt;em&gt;stdout&lt;/em&gt; prematurely after a failed transaction.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I didn&amp;rsquo;t bother implementing this within my example, as it wasn&amp;rsquo;t essential to understanding the code.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;jruby-example&#34;&gt;JRuby example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If Clojure is a bit too much of a head spin (Lisp based languages can be quite confusing if you&amp;rsquo;re new to the syntax/concepts) then let&amp;rsquo;s see a similar example written in JRuby.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;because JRuby runs on the JVM, like Clojure, we take advantage of that fact and import Clojure&amp;rsquo;s STM functionality for us to utilise within our Ruby code&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;In the following example we have downloaded the Clojure runtime as a jar (from &lt;a href=&#34;http://clojure.org/downloads&#34; target=&#34;_blank&#34;&gt;http://clojure.org/downloads&lt;/a&gt;) and are adding its location to the Java &lt;code&gt;$CLASSPATH&lt;/code&gt; environment variable so when we try to &lt;code&gt;java_import&lt;/code&gt; the relevant libraries, Java will be able to locate them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Within our code you&amp;rsquo;ll see we&amp;rsquo;re using methods that correlate to what would be recognisable to Clojure&amp;rsquo;s environment: &lt;code&gt;LockingTransaction.run_in_transaction&lt;/code&gt;, &lt;code&gt;@balance.set&lt;/code&gt; and &lt;code&gt;@balance.deref&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;$CLASSPATH &amp;lt;&amp;lt; &amp;quot;clojure-1.6.0/clojure-1.6.0.jar&amp;quot;&#xA;&#xA;require &amp;quot;java&amp;quot;&#xA;java_import &amp;quot;clojure.lang.Ref&amp;quot;&#xA;java_import &amp;quot;clojure.lang.LockingTransaction&amp;quot;&#xA;&#xA;class Account&#xA;  attr_reader :name&#xA;&#xA;  def initialize(name, initial_balance)&#xA;    @name    = name&#xA;    @balance = Ref.new initial_balance&#xA;  end&#xA;&#xA;  def balance&#xA;    @balance.deref&#xA;  end&#xA;&#xA;  def deposit(amount)&#xA;    LockingTransaction.run_in_transaction do&#xA;      if amount &amp;gt; 0&#xA;        @balance.set @balance.deref + amount&#xA;        p &amp;quot;Deposited $#{amount} into account #{@name}&amp;quot;&#xA;      else&#xA;        raise &amp;quot;The amount must be greater than zero&amp;quot;&#xA;      end&#xA;    end&#xA;  end&#xA;&#xA;  def withdraw(amount)&#xA;    LockingTransaction.run_in_transaction do&#xA;      if amount &amp;gt; 0 &amp;amp;&amp;amp; @balance.deref &amp;gt;= amount&#xA;        @balance.set @balance.deref - amount&#xA;      else&#xA;        raise &amp;quot;Can&#39;t withdraw $#{amount}; balance is $#{@balance.deref}&amp;quot;&#xA;      end&#xA;    end&#xA;  end&#xA;end&#xA;&#xA;def transfer(from, to, amount)&#xA;  LockingTransaction.run_in_transaction do&#xA;    to.deposit amount&#xA;    from.withdraw amount&#xA;  end&#xA;end&#xA;&#xA;def transfer_and_print(from, to, amount)&#xA;  begin&#xA;    transfer from, to, amount&#xA;  rescue StandardError =&amp;gt; e&#xA;    p &amp;quot;Transfer failed: #{e}&amp;quot;&#xA;  end&#xA;&#xA;  p &amp;quot;Balance of &#39;from&#39; account (#{from.name}) is $#{from.balance}&amp;quot;&#xA;  p &amp;quot;Balance of &#39;to&#39; account (#{to.name}) is $#{to.balance}&amp;quot;&#xA;end&#xA;&#xA;account1 = Account.new 1, 2000&#xA;account2 = Account.new 2, 100&#xA;&#xA;p &amp;quot;account1 balance is $#{account1.balance}&amp;quot;&#xA;p &amp;quot;account2 balance is $#{account2.balance}&amp;quot;&#xA;p &amp;quot;---&amp;quot;&#xA;&#xA;transfer_and_print account1, account2, 500&#xA;p &amp;quot;---&amp;quot;&#xA;transfer_and_print account1, account2, 5000&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The output of the above program is as follows… (notice that we see the deposit succeeds, but the transaction as a whole fails - i.e. the deposit is revoked - as we can&amp;rsquo;t withdraw the requested amount)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;quot;account1 balance is $2000&amp;quot;&#xA;&amp;quot;account2 balance is $100&amp;quot;&#xA;&amp;quot;---&amp;quot;&#xA;&amp;quot;Deposited $500 into account 2&amp;quot;&#xA;&amp;quot;Balance of &#39;from&#39; account (1) is $1500&amp;quot;&#xA;&amp;quot;Balance of &#39;to&#39; account (2) is $600&amp;quot;&#xA;&amp;quot;---&amp;quot;&#xA;&amp;quot;Deposited $5000 into account 2&amp;quot;&#xA;&amp;quot;Transfer failed: Can&#39;t withdraw $5000; balance is $1500&amp;quot;&#xA;&amp;quot;Balance of &#39;from&#39; account (1) is $1500&amp;quot;&#xA;&amp;quot;Balance of &#39;to&#39; account (2) is $600&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;actors&#34;&gt;Actors&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The basic premise of the Actors pattern is built upon it being a form of &amp;ldquo;message bus&amp;rdquo;. The philosophy of the pattern is that &lt;em&gt;everything is an Actor&lt;/em&gt;. An Actor receives messages and based on its state can determine whether it wants to handle the task defined in the message it has received, or to delegate the task off to other subordinates. An Actor can also create more Actors dynamically.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each Actor is typically run in their own thread (using a Thread Pool implementation to allow for better resource management/allocation). This also helps to facilitate &amp;ldquo;isolated mutability&amp;rdquo;; i.e. mutable state is contained within the Actor but only that actor can modify the state (and as the Actor sits inside it&amp;rsquo;s own thread its mutable state is safe from other Actors).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;be very careful using the Actor pattern with languages that do not have native support for immutable data structures as you could open yourself up to hard to debug problems if your language allows mutability (e.g. Clojure supports immutability, but Ruby does not; Ruby does allow you to &lt;code&gt;freeze&lt;/code&gt; an object, but that doesn&amp;rsquo;t include any nested structures). Much like how we&amp;rsquo;ve utilised Clojure&amp;rsquo;s STM in the above JRuby example, you can also import its immutable data structures. Although this won&amp;rsquo;t help you if you&amp;rsquo;re forced to use a non-JVM language such as MRI (which is the main Ruby interpreter written in C).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The use of messages allows communication to become asynchronous and loosely coupled from the rest of the system. But this can result in non-sequential message order (unless you have an Actor whose role is to ensure ordering via some form of Queue).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Actor pattern has been made popular via Erlang and Scala (in the form of the &lt;a href=&#34;http://akka.io/&#34; target=&#34;_blank&#34;&gt;Akka&lt;/a&gt; framework)&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Akka has bindings for other JVM based languages (Clojure, JRuby, Groovy): &lt;a href=&#34;http://doc.akka.io/docs/akka/2.3.4/additional/language-bindings.html&#34; target=&#34;_blank&#34;&gt;http://doc.akka.io/docs/akka/2.3.4/additional/language-bindings.html&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve yet to get around to writing any Scala code and so because Scala is the defacto example of the Akka framework I&amp;rsquo;ve decided to borrow an example from the official Akka site:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;case class Greeting(who: String)&#xA; &#xA;class GreetingActor extends Actor with ActorLogging {&#xA;  def receive = {&#xA;    case Greeting(who) ⇒ log.info(&amp;quot;Hello &amp;quot; + who)&#xA;  }&#xA;}&#xA; &#xA;val system = ActorSystem(&amp;quot;MySystem&amp;quot;)&#xA;val greeter = system.actorOf(Props[GreetingActor], name = &amp;quot;greeter&amp;quot;)&#xA;greeter ! Greeting(&amp;quot;Charlie Parker&amp;quot;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;transactions-and-actors&#34;&gt;Transactions and Actors?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Actors can also coordinate more safely by combining themselves via STM transactions. These are typically referred to as &amp;ldquo;transactors&amp;rdquo;. The benefits of wrapping messages within a transaction is that we eliminate synchronisation concerns (i.e. as changes within a transaction are purposely &lt;em&gt;atomic&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in Clojure, when sending an action to an agent from inside a transaction, the call is still non-blocking and yet it also still abides by the STM rules (i.e. the action is &lt;em&gt;held&lt;/em&gt; until the transaction commits)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;actors-in-clojure&#34;&gt;Actors in Clojure&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Clojure does not support Actors, although it does have a mechanism known as &amp;ldquo;&lt;a href=&#34;http://clojure.org/agents&#34; target=&#34;_blank&#34;&gt;agents&lt;/a&gt;&amp;rdquo;. An agent provides access to shared mutable state, but does so asynchronously (much like an Actor). Where an Actor receives a &amp;ldquo;message&amp;rdquo;, an agent accepts an &lt;code&gt;action&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;Actors and Agents have some surface similarities, but ultimately are different beasts. Actors &amp;ldquo;encapsulates&amp;rdquo; state and provides no means to access it from the outside. Whereas Agents contain a single value that can be retrieved and manipulated (via &lt;code&gt;send&lt;/code&gt; or &lt;code&gt;send-off&lt;/code&gt; - see below for details). Actors also encapsulate behaviour, whereas an Agent is provided the function that affects its value. Actors can be distributed, whereas Agents cannot&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Whereas the STM provides coordinated access to data (i.e. atomic - it verifies that there are no changes to shared data that has been written to; otherwise it&amp;rsquo;ll cause the entire transaction to fail). Agents are independent; meaning that actions run concurrently (the call to &lt;code&gt;action&lt;/code&gt; returns immediately), but the actions are executed sequentially via a separate thread. So where a transaction is a synchronous operation, an action handled by an agent is &lt;em&gt;asynchronous&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Clojure, agents are transaction aware (whereas atoms are not) and the &lt;code&gt;!&lt;/code&gt; at end of function name is an indicator of this: &lt;code&gt;swap!&lt;/code&gt; (not coordinated) vs &lt;code&gt;send&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the agent API in Clojure provides two methods: &lt;code&gt;send-off&lt;/code&gt; and &lt;code&gt;send&lt;/code&gt;. The former creates a new thread specifically for that agent; whereas the latter selects a thread from a pre-defined thread pool. The problem with &lt;code&gt;send&lt;/code&gt; is that agents fight for an available thread and so if your action does blocking I/O then you&amp;rsquo;ll delay other agents from working (and thus reducing the extra concurrency benefits of using a thread pool)&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Once the agent&amp;rsquo;s state is changed, the next action is applied to the agent (now using the latest state it points to).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;differences-between-agents-and-erlang-actors&#34;&gt;Differences between Agents and Erlang Actors&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is one distinctive difference between Erlang&amp;rsquo;s Actor and Clojure&amp;rsquo;s Agent, which is that an Agents &amp;ldquo;action&amp;rdquo; doesn&amp;rsquo;t block additional value request calls like an Erlang &amp;ldquo;message&amp;rdquo;. This is demonstrated in the following image, but in summary: requests to an Actor are blocked until a response to the previous message can be provided; whereas Clojure Agents allow multiple &lt;code&gt;@deref&lt;/code&gt; calls to be made and processed:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/actors-vs-agents.png&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/actors-vs-agents.png&#34; alt=&#34;actors vs agents&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;in the above image we have two simultaneous requests to &amp;ldquo;increment&amp;rdquo; the value held by the Actor/Agent. One can succeed, the other goes onto a queue and is applied after the first call finishes.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;limitations&#34;&gt;Limitations&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The Actor pattern does have some limitations:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Languages that do not enforce immutability are more prone to thread safety bugs&lt;/li&gt;&#xA;&lt;li&gt;Actors can be left starving if a dependant Actor fails (they&amp;rsquo;ll be left waiting for a message that will never arrive)&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This means we should program defensively and raise exceptions to the waiting Actors&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;The Actors pattern does not prevent a dead/livelock scenario (two Actors waiting on each other for messages)&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Again, we should program defensively by using timeouts to break a livelock&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Actors can only handle one message at a time, meaning we should be careful to not cause delays for messages that are only trying to &amp;ldquo;read&amp;rdquo; a value from inside the Actor&lt;/li&gt;&#xA;&lt;li&gt;The Actor pattern works best when problems can be divided into sections that do not rely on each other&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;i.e. communication can be sporadic. If frequent interaction is needed or each section has a dependency on each other to coordinate the task then choose an alternative combination of concurrency models&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;csp&#34;&gt;CSP&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Communicating Sequential Processes is an alternative mechanism for expressing concurrency, which has been popularized by recent languages &lt;a href=&#34;http://clojure.org/&#34; target=&#34;_blank&#34;&gt;Clojure&lt;/a&gt; and &lt;a href=&#34;http://golang.org/&#34; target=&#34;_blank&#34;&gt;Go&lt;/a&gt;. It also is based on the idea of message passing, similar to the Actor pattern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some of the fundamental differences between this and the Actor pattern are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Messages are sequential&lt;/li&gt;&#xA;&lt;li&gt;Communication is synchronous&lt;/li&gt;&#xA;&lt;li&gt;Communication happens via defined &amp;ldquo;channels&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;Processes are anonymous&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;i.e. Actors know who to communicate with&lt;/li&gt;&#xA;&lt;li&gt;Whereas Channels are pipes with messages going in and listeners the other end&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You also have the option of applying other patterns such as multiplexing multiple channels down into one, think &amp;ldquo;fan-in&amp;rdquo;, which can help in certain scenarios where you want to accept lots of messages comming in (the reverse is also possible, i.e. &amp;ldquo;fan-out&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Picking one model over another (Actor vs CSP) will be determined by the level of complexity you feel is inherently added by either solution and/or model your language of choice supports.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following is an extremely simple demonstration of the CSP/channel model written in Go (there is a channel which accepts an infinite number of messages; and our &lt;code&gt;main&lt;/code&gt; function will take the messages from the channel as they become available):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;math/rand&amp;quot;&#xA;    &amp;quot;time&amp;quot;&#xA;)&#xA;&#xA;func main() {&#xA;    c := createChannel(&amp;quot;hello&amp;quot;, 5)&#xA;&#xA;    for i := range c {&#xA;        fmt.Printf(&amp;quot;You say: %q\n&amp;quot;, i)&#xA;    }&#xA;&#xA;    fmt.Println(&amp;quot;I&#39;m done.&amp;quot;)&#xA;}&#xA;&#xA;func createChannel(msg string, size int) &amp;lt;-chan string {&#xA;    c := make(chan string, size)&#xA;&#xA;    go func() {&#xA;        for i := 1; i &amp;lt;= size; i++ {&#xA;            c &amp;lt;- fmt.Sprintf(&amp;quot;%s %d&amp;quot;, msg, i)&#xA;            time.Sleep(time.Duration(rand.Intn(1e3)) * time.Millisecond)&#xA;        }&#xA;        close(c)&#xA;    }()&#xA;&#xA;    return c&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Again, it&amp;rsquo;s important to realise that Channels are synchronous and can block/cause deadlocks. In Go you can implement a timeout as a way of avoiding deadlocks. I&amp;rsquo;m not currently sure if Clojure has a similar work-around built into the language or whether you have to manually implement that yourself.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;threads&#34;&gt;Threads&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Threads are prevalent across both the &amp;ldquo;shared memory&amp;rdquo; and &amp;ldquo;message passing&amp;rdquo; models. The discussion of how many threads to create is an important one and depends on the type of tasks your application is expected to handle: CPU bound or I/O bound. In the following sections we&amp;rsquo;ll cover this topic, as well as describing an algorithm for calculating this.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;what-is-cpu-bound-vs-i-o-bound&#34;&gt;What is CPU bound vs I/O bound?&lt;/h3&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the following is credited to &lt;a href=&#34;http://yaoyao.codes/os/2017/03/20/cpu-bound-vs-io-bound&#34; target=&#34;_blank&#34;&gt;yaoyao.codes&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;CPU bound&lt;/strong&gt;: the rate at which a process progresses is limited by the speed of the CPU.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I/O bound&lt;/strong&gt;: the rate at which a process progresses is limited by the speed of the I/O subsystem.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This means a task that performs calculations on a small set of numbers, for example multiplying small matrices, is likely to be CPU bound. While a task that processes data from disk, for example, counting the number of lines in a file is likely to be I/O bound.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A program is CPU bound if it would go faster if the CPU were faster.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A program is I/O bound if it would go faster if the I/O subsystem was faster.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following is an explanation from &amp;ldquo;Essentials of Computer Organization and Architecture&amp;rdquo;&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Input and output (I/O) devices allow us to communicate with the computer system. I/O is the transfer of data between primary memory and various I/O peripherals. These devices are not connected directly to the CPU. Instead, there is an interface that handles the data transfers. This interface converts the system bus signals to and from a format that is acceptable to the given device. The CPU communicates to these external devices via I/O registers.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;See also the following image that demonstrates how a CPU will allow interruptions for I/O based signals (&lt;a href=&#34;https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/13_IOSystems.html&#34; target=&#34;_blank&#34;&gt;source&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/assets/img/cpu-io.jpg&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;/assets/img/cpu-io.jpg&#34; alt=&#34;cpu io&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A CPU/Processor can contain one or more cores. For example, a quad core processor that runs at speed of 3GHz will have 4 cores running at that speed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I/O, whether a file system interaction or a network request - e.g. HTTP, TCP or Socket based - can block other processes; and so if the application is designed to work concurrently (e.g. there are other threads the CPU can jump to in the mean time) then the current thread will be left to finish and another thread will be picked up instead (this is how concurrency works - the CPU interleaves between threads - this should also clarify how concurrency &lt;em&gt;is not&lt;/em&gt; the same thing as paralleism).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For computational intensive operations you&amp;rsquo;ll want the number of threads to be equal to the number of cores available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For I/O intensive operations you&amp;rsquo;ll want more threads than available cores. This is because (as explained above) the CPU/Processor will &amp;ldquo;context switch&amp;rdquo; to another thread when the current thread is blocked (hence it is better to have more threads than cores for I/O).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;calculating-the-number-of-threads&#34;&gt;Calculating the number of Threads&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To calculate how many more threads than cores you&amp;rsquo;ll need for an intensive set of I/O operations, use the following algorithm:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Number of Threads = Number of Available Cores / (1 - Blocking Coefficient)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the blocking coefficient (coefficient being a fancy word that means: a value used as a multiplier) is different depending on the operation. For a computational operation it is 0, whereas a fully blocking operation it is 1.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;An example of a blocking coefficient would be: &lt;code&gt;0.9&lt;/code&gt; - which means a task blocks 90% (&lt;code&gt;0.9&lt;/code&gt;) of the time &amp;amp; works only 10% (&lt;code&gt;0.1&lt;/code&gt;) of the time. Meaning, if you had 2 cores then you&amp;rsquo;d want 20 threads.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;2 / (1 - 0.9) = 20&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;even-workload-distribution&#34;&gt;Even workload distribution&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you have two cores and a very large queue of messages to process, then your initial thought would maybe be to split the queue (i.e. the tasks) into two. This would mean you could have two threads running (i.e. utilising both cores); the first thread processing the first queue data and the second thread handling the other half of the queue data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with this solution is that is doesn&amp;rsquo;t necessarily guarantee even distribution of the tasks across your available cores. If our queue data consisted of a computational task such as calculating prime numbers then the first half of the queue would take a lot less time to process because the smaller prime numbers would take less time to calculate than the other queue (which if evenly split in two would mean the other queue would have the much larger prime numbers to calculate).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means one core will be sitting idle while the other core is still processing data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What would be better is to have more &lt;em&gt;parts&lt;/em&gt; than threads/cores. So if one &amp;ldquo;part&amp;rdquo; finishes more quickly than expected, then another part can be picked up. Simply diving our tasks into two parts means one core will likely be sitting idle for longer than the other core. But if we divide our tasks into more granular parts, then we can aim to utilise as much of each core as possible.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As mentioned at the start of this post: solving the problem of thread-safe concurrency isn&amp;rsquo;t necessarily as straight forward as you would have hoped (if you&amp;rsquo;re new to the concepts). Throw in distributed systems and the problem is conflated even further.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But with that being said, we can clearly see there are quite a few different options available to us already - albeit with differing levels of complexity depending on the problem we&amp;rsquo;re trying to solve. This is a good thing because you shouldn&amp;rsquo;t always reach for a more complex solution if it&amp;rsquo;s not necessary. If the problem is a small one and a simple mutex resolves it then maybe that&amp;rsquo;s OK. Don&amp;rsquo;t over engineer your system.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/concurrency/</guid>
      <link>https://www.integralist.co.uk/posts/concurrency/</link>
      <pubDate>Sun, 28 Dec 2014 00:00:00 +0000</pubDate>
      <title>Thread Safe Concurrency</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a quick post to cover a GitHub workflow that is utilised by our specific team (Frameworks) here at BBC News. The basis of our workflow is this:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Open a GitHub PR (Pull Request) by creating a new feature branch from &lt;code&gt;master&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Make feature specific changes and request a code review&lt;/li&gt;&#xA;&lt;li&gt;If given a &amp;ldquo;thumbs up&amp;rdquo;, this means the PR author is allowed to handle merging the PR&lt;/li&gt;&#xA;&lt;li&gt;The merge process requires a set of sub steps (see below)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;rebase-before-merge&#34;&gt;Rebase before merge&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;At this point the PR author has been given a &amp;ldquo;thumbs up&amp;rdquo; and is preparing their PR to be merged back into the &lt;code&gt;master&lt;/code&gt; branch. The steps (in summary) are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Interactively rebase &lt;code&gt;master&lt;/code&gt; onto the feature branch&lt;/li&gt;&#xA;&lt;li&gt;Squash all feature commits into a single commit:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;we&amp;rsquo;ll see an example of this later (as this isn&amp;rsquo;t &lt;em&gt;exactly&lt;/em&gt; a &lt;code&gt;squash&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;the first line of the commit message should be the same as the GitHub PR title&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;As part of the rebase ensure:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the author(s) is mentioned in the commit message&lt;/li&gt;&#xA;&lt;li&gt;the PR is mentioned (and any associated issues as well)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Move back to the &lt;code&gt;master&lt;/code&gt; branch and &lt;code&gt;cherry-pick&lt;/code&gt; in the newly squashed feature commit&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below is an example set of commits we&amp;rsquo;ll be working from. I create a master branch and then branch off from that with a new &lt;code&gt;feature&lt;/code&gt; branch:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git init&#xA;touch test.txt&#xA;git commit -am &amp;quot;Initial file&amp;quot;&#xA;&#xA;[master (root-commit) 85919e1] Initial file&#xA; 1 file changed, 0 insertions(+), 0 deletions(-)&#xA; create mode 100644 test.txt&#xA;&#xA;git checkout -b feature&#xA;Switched to a new branch &#39;feature&#39;&#xA;&#xA;echo foo &amp;gt;&amp;gt; test.txt&#xA;git commit -am &amp;quot;Foo&amp;quot;&#xA;&#xA;echo bar &amp;gt;&amp;gt; test.txt&#xA;git commit -am &amp;quot;Bar&amp;quot;&#xA;&#xA;echo baz &amp;gt;&amp;gt; test.txt&#xA;git commit -am &amp;quot;Baz&amp;quot;&#xA;&#xA;# Check commits we now have in this feature branch&#xA;# Note: this is a custom shell alias&#xA;git lg&#xA;&#xA;* 62d4c80 - Baz (HEAD, feature)&#xA;* a5827db - Bar&#xA;* ae1a4a5 - Foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point, let&amp;rsquo;s imagine our &lt;code&gt;feature&lt;/code&gt; PR has been approved to be merged:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Make sure master is up to date&#xA;git checkout master&#xA;git pull --rebase origin master&#xA;&#xA;# Carry out the interactive rebase&#xA;git checkout feature&#xA;git rebase -i master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now at this point you should see something like the following in your terminal:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;pick ae1a4a5 Foo&#xA;pick a5827db Bar&#xA;pick 62d4c80 Baz&#xA;&#xA;# Rebase 85919e1..62d4c80 onto 85919e1&#xA;#&#xA;# Commands:&#xA;#  p, pick = use commit&#xA;#  r, reword = use commit, but edit the commit message&#xA;#  e, edit = use commit, but stop for amending&#xA;#  s, squash = use commit, but meld into previous commit&#xA;#  f, fixup = like &amp;quot;squash&amp;quot;, but discard this commit&#39;s log message&#xA;#  x, exec = run command (the rest of the line) using shell&#xA;#&#xA;# These lines can be re-ordered; they are executed from top to bottom.&#xA;#&#xA;# If you remove a line here THAT COMMIT WILL BE LOST.&#xA;#&#xA;# However, if you remove everything, the rebase will be aborted.&#xA;#&#xA;# Note that empty commits are commented out&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We&amp;rsquo;re now ready to modify our git history. So let&amp;rsquo;s squash all our commits down into a single commit:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;reword ae1a4a5 Foo&#xA;fixup a5827db Bar&#xA;fixup 62d4c80 Baz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;we don&amp;rsquo;t use &lt;code&gt;squash&lt;/code&gt; as that automatically uses the existing commit message from the commit we&amp;rsquo;re squashing other commits into (but our requirements mean we wish to modify that commit message); so we use &lt;code&gt;reword&lt;/code&gt; and &lt;code&gt;fixup&lt;/code&gt; instead&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s apply these changes by executing &lt;code&gt;:wq&lt;/code&gt;. Once you do this, Git will carry out the rebase and then drop you back to the &lt;code&gt;COMMIT_EDITMSG&lt;/code&gt; screen. You can now modify the commit message so it is the same as the title of your GitHub PR (and you can inform GitHub of what PR to automatically close when this commit arrives in &lt;code&gt;master&lt;/code&gt; by using the keyword: &lt;a href=&#34;https://help.github.com/articles/closing-issues-via-commit-messages/&#34; target=&#34;_blank&#34;&gt;closes&lt;/a&gt;; you&amp;rsquo;ll notice there is the keyword &lt;code&gt;fixes&lt;/code&gt; which indicates a GitHub issue to close).&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;New Feature X&#xA;&#xA;Closes #1 and Fixes #11&#xA;Authors @integralist @stevenjack&#xA;# Please enter the commit message for your changes. Lines starting&#xA;# with &#39;#&#39; will be ignored, and an empty message aborts the commit.&#xA;#&#xA;# Date:      Sat Dec 27 16:19:54 2014 +0000&#xA;#&#xA;# rebase in progress; onto 85919e1&#xA;# You are currently editing a commit while rebasing branch &#39;feature&#39; on &#39;85919e1&#39;.&#xA;#&#xA;# Changes to be committed:&#xA;#    modified:   test.txt&#xA;#&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can now see (when executing &lt;code&gt;git log&lt;/code&gt;) that the three individual feature commits are now a single commit with a commit hash of &lt;code&gt;68f5bee&lt;/code&gt;. We can move back to &lt;code&gt;master&lt;/code&gt; (i.e. &lt;code&gt;git checkout master&lt;/code&gt;) and then &lt;code&gt;cherry-pick&lt;/code&gt; the squashed commit into it:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout master&#xA;git cherry-pick 68f5bee&#xA;git branch -D feature&#xA;git push origin master&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;bonus-modifying-content-within-an-interactive-rebase&#34;&gt;(Bonus) Modifying content within an interactive rebase&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One aspect of carrying out an interactive rebase that seems to confuse a lot of users is the ability to edit the content of a specific commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I think the reason being is that when you select a commit to &lt;code&gt;edit&lt;/code&gt;, the interactive rebase drops you at that specific commit, so you&amp;rsquo;ll find there aren&amp;rsquo;t any files in the staging area.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To make edits at that point you need to undo the commit, so the files end up back in the staging area, ready to be modified and a new commit made.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at an example, using our earlier example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git lg&#xA;&#xA;* 76c99a2 - New Feature X (HEAD, master)&#xA;* 85919e1 - Initial file&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s say we want to make an edit to the commit &lt;code&gt;76c99a2&lt;/code&gt;. To do that we&amp;rsquo;ll need to start up an interactive rebase like so (we specify the commit before the one we want to edit):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase -i 85919e1&#xA;&#xA;Stopped at 76c99a27e64b5f749ac8e3d3c7032f53954c760a... New Feature X&#xA;You can amend the commit now, with&#xA;&#xA;        git commit --amend &#xA;&#xA;Once you are satisfied with your changes, run&#xA;&#xA;        git rebase --continue&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At this point we want to execute the following command, which will undo the commit (but keeps the changes from that commit) and place the files back into the staging area:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git reset --mixed 85919e1&#xA;&#xA;Unstaged changes after reset:&#xA;M       test.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Now if you check the diff on the files you&amp;rsquo;ll see the changes from that commit have been made and are waiting to be committed again:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff&#xA;&#xA;diff --git a/test.txt b/test.txt&#xA;index e69de29..86e041d 100644&#xA;--- a/test.txt&#xA;+++ b/test.txt&#xA;@@ -0,0 +1,3 @@&#xA;+foo&#xA;+bar&#xA;+baz&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So you can now modify the &lt;code&gt;test.txt&lt;/code&gt; file as necessary and create a new commit. When you create the new commit you finish the rebase by using the &lt;code&gt;--continue&lt;/code&gt; feature (as seen in the above output when initially starting the rebase):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo qux &amp;gt;&amp;gt; test.txt&#xA;git commit -am &amp;quot;New Feature X&amp;quot;&#xA;git rebase --continue&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you forget where you are then running &lt;code&gt;git status&lt;/code&gt; should give you the information you need to help you either continue rebasing or to abort the rebase&lt;/p&gt;&lt;/div&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/github-workflow/</guid>
      <link>https://www.integralist.co.uk/posts/github-workflow/</link>
      <pubDate>Sat, 27 Dec 2014 00:00:00 +0000</pubDate>
      <title>GitHub Workflow</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post isn&amp;rsquo;t about &lt;a href=&#34;http://en.wikipedia.org/wiki/Functional_Programming&#34; target=&#34;_blank&#34;&gt;Functional Programming&lt;/a&gt; per se, as there are many parts to pure FP (seen in Lisp, Clojure, Haskell etc) which we can&amp;rsquo;t achieve completely in the JavaScript language (for example, implementing fundamental principles of FP such as &amp;ldquo;immutable data&amp;rdquo; is very difficult in a language designed around allowing data structures to be mutable. Although immutable data would be a lot easier with ES5 getters/setters and ES6 proxies).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What we do cover is recursion and a problem known as &amp;ldquo;tail call optimisation&amp;rdquo; and how to work around it in JavaScript.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-problem&#34;&gt;The problem&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In JavaScript, if a function calls itself recursively then the JavaScript engine has to create what&amp;rsquo;s called a new &amp;lsquo;stack&amp;rsquo;. A stack is a chunk of memory allocated to help keep track of all the information related to the function at the point of execution (such as its arguments and their initialised values).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here in lies the problem: creating stacks is expensive, as the JavaScript engine can only create as many stacks as it has memory available. If we write a function that recursively calls itself many times then we&amp;rsquo;ll find that we can exhaust the memory allocation and trigger an error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at some code that demonstrates this.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following function &lt;code&gt;sum&lt;/code&gt; simply adds two numbers together; but for the purpose of demonstrating recursion (a potentially complex topic) and making it easier to understand, we have written the &lt;code&gt;sum&lt;/code&gt; function in a very convoluted way:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function sum(x, y) {&#xA;    if (y &amp;gt; 0) {&#xA;      return sum(x + 1, y - 1);&#xA;    } else {&#xA;      return x;&#xA;    }&#xA;}&#xA;&#xA;sum(1, 10); // =&amp;gt; 11&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s quickly explain what the code does:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We pass in two numbers which are assigned to the parameters &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; (in this instance we pass &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;We check if &lt;code&gt;y&lt;/code&gt; is greater than &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;If &lt;code&gt;y&lt;/code&gt; is greater than &lt;code&gt;0&lt;/code&gt; (which we know it is) then we recursively call &lt;code&gt;sum&lt;/code&gt; again but this time modify the arguments so that &lt;code&gt;x&lt;/code&gt; is incremented by &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; is reduced by &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;When the &lt;code&gt;sum&lt;/code&gt; function is next called we&amp;rsquo;re passing &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;9&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;At this point we&amp;rsquo;re now back inside the &lt;code&gt;sum&lt;/code&gt; function but the first call to &lt;code&gt;sum&lt;/code&gt; has yet to finish (as we didn&amp;rsquo;t reach the end of the function, the focus moved to another function being executed - which in this case was &lt;code&gt;sum&lt;/code&gt; again)&lt;/li&gt;&#xA;&lt;li&gt;Also at this point the JavaScript engine has two stacks. One for the point in time when we passed in &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt;, and now (as it has to remember &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;9&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;The JavaScript engine has to remember the previous arguments &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt; because potentially once this second &lt;code&gt;sum&lt;/code&gt; execution finishes we&amp;rsquo;ll end up back in the first execution context.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As we can see, in the above code the JavaScript engine has to create a new stack for each recursive call. For a small sum of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt; this is fine; but if we try to sum &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;100000&lt;/code&gt; then that&amp;rsquo;ll require more stacks than we have memory to allocate. This will cause an error like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sum(1, 100000);&#xA;// =&amp;gt; `RangeError: Maximum call stack size exceeded`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Recursion in the form we&amp;rsquo;ve written it above requires many stacks to be created because of how the function is calling itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first call to the &lt;code&gt;sum&lt;/code&gt; function (i.e. &lt;code&gt;sum(1, 100000)&lt;/code&gt;) doesn&amp;rsquo;t complete until the very &lt;em&gt;last&lt;/em&gt; call to &lt;code&gt;sum&lt;/code&gt; returns the value of &lt;code&gt;x&lt;/code&gt; (i.e. &lt;code&gt;sum(0, 99999)&lt;/code&gt; is technically the final execution). When the final call to &lt;code&gt;sum&lt;/code&gt; occurs and we discover that &lt;code&gt;y&lt;/code&gt; is no longer greater than zero, we return the accumulated value which has (for each recursive call) been stored inside the argument &lt;code&gt;x&lt;/code&gt;. That returned value needs to then be passed back through each function execution context (effectively closing each stack) until we reach the very first function execution context that was opened when we ran &lt;code&gt;sum(1, 100000)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we create a stack deep enough (such as we did with &lt;code&gt;sum(1, 100000)&lt;/code&gt;) then the JavaScript engine will throw a &lt;code&gt;Maximum call stack size exceeded&lt;/code&gt; error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This problem can occur very easily (as we&amp;rsquo;ve seen in this simple code example).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tail-call-optimisation&#34;&gt;Tail Call Optimisation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In other programming languages the recursion could be rewritten in such a way that the engine would recognise a recursive execution was happening and optimise the code internally into a loop form. This is called a &amp;ldquo;tail call optimisation&amp;rdquo; (TCO).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unfortunately the JavaScript language doesn&amp;rsquo;t implement this optimisation.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;apparently ECMAScript 6 has plans to implement TCO&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The following is an example of a tail optimised version of the previous code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function sum(x, y) {&#xA;    function recur(a, b) {&#xA;        if (b &amp;gt; 0) {&#xA;            return recur(a + 1, b - 1);&#xA;        } else {&#xA;            return a;&#xA;        }&#xA;    }&#xA;&#xA;    return recur(x, y);&#xA;}&#xA;&#xA;sum(1, 10); // =&amp;gt; 11&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This works because the &lt;code&gt;recur&lt;/code&gt; function ends up being the last invocation of the &lt;code&gt;sum&lt;/code&gt; function. Now the engine is able to construct internal code that executes &lt;code&gt;recur&lt;/code&gt; inside of a loop instead of via recursion.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As mentioned above, this optimisation has no effect in the current version of the JavaScript language (fingers crossed ES6 will implement TCO so the above code would work fine).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For now, we need an alternative solution.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;the-solution&#34;&gt;The solution&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The fix to this problem (in JavaScript at least) is to consume fewer stacks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way we could do this is to rewrite the code to not be recursive; so in other words: use a loop! Effectively we would be producing our own implementation of TCO (remember that TCO recognises a recursion and internally implements it as a loop).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with using a loop is that it&amp;rsquo;s not as elegant as the recursive style we associate with functional programming.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another solution is to use a type of functional pattern called &amp;ldquo;trampolining&amp;rdquo;. Let&amp;rsquo;s take a look at one implementation of it&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;trampolining&#34;&gt;Trampolining&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Note: the following code (and my explanation of it) assumes an understanding of the &lt;code&gt;this&lt;/code&gt; keyword and changing its context. If you&amp;rsquo;re unsure about what this means then read more about it &lt;a href=&#34;https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&amp;amp;%20object%20prototypes/README.md&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function trampoline(f) {&#xA;    while (f &amp;amp;&amp;amp; f instanceof Function) {&#xA;        f = f();&#xA;    }&#xA;    return f;&#xA;}&#xA;&#xA;function sum(x, y) {&#xA;    function recur(x, y) {&#xA;        if (y &amp;gt; 0) {&#xA;          return recur.bind(null, x + 1, y - 1);&#xA;        } else {&#xA;          return x;&#xA;        }&#xA;    }&#xA;&#xA;    return trampoline(recur.bind(null, x, y));&#xA;}&#xA;&#xA;sum(1, 10); // =&amp;gt; 11&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The reason the above code works is because we&amp;rsquo;ve replaced our functional recursion style with a loop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above code we don&amp;rsquo;t create a deep nest of stacks because the &lt;code&gt;sum&lt;/code&gt; function only gets called once. The &lt;code&gt;trampoline&lt;/code&gt; function also is only called once; and the &lt;code&gt;recur&lt;/code&gt; function inside of &lt;code&gt;sum&lt;/code&gt;, although called multiple times, is called via a loop (again, no more than one stack is required at any one time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The code breaks down like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We call &lt;code&gt;sum(1, 10)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Our &lt;code&gt;sum&lt;/code&gt; function ultimately returns a value. In this case whatever is returned by calling the &lt;code&gt;trampoline&lt;/code&gt; function.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;trampoline&lt;/code&gt; function accepts a &lt;em&gt;reference&lt;/em&gt; to a function as its argument (it&amp;rsquo;s important to understand it needs a &lt;em&gt;reference&lt;/em&gt; to a function; doing &lt;code&gt;return trampoline(recur(x, y))&lt;/code&gt; wouldn&amp;rsquo;t work as that would end up passing the result of calling &lt;code&gt;recur(x, y)&lt;/code&gt; to the &lt;code&gt;trampoline&lt;/code&gt; function).&lt;/li&gt;&#xA;&lt;li&gt;So we use &lt;code&gt;Function#bind&lt;/code&gt; to pass a reference to the &lt;code&gt;recur&lt;/code&gt; function (we use &lt;code&gt;null&lt;/code&gt; as the &lt;code&gt;this&lt;/code&gt; binding because it doesn&amp;rsquo;t matter what the context the function executes in as we don&amp;rsquo;t use the function as a constructor).&lt;/li&gt;&#xA;&lt;li&gt;When we execute &lt;code&gt;sum(1, 10)&lt;/code&gt; we pass the reference to the internal &lt;code&gt;recur&lt;/code&gt; method to the &lt;code&gt;trampoline&lt;/code&gt; function.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;trampoline&lt;/code&gt; function checks if we passed a function and if so we execute the function and store its return value inside the &lt;code&gt;f&lt;/code&gt; variable.&lt;/li&gt;&#xA;&lt;li&gt;If what we pass into the &lt;code&gt;trampoline&lt;/code&gt; function isn&amp;rsquo;t a function then we assume it&amp;rsquo;s the end (i.e. accumulated) value and we return the value straight back to the &lt;code&gt;sum&lt;/code&gt; function which returns that value as the accumulated value.&lt;/li&gt;&#xA;&lt;li&gt;Inside the &lt;code&gt;recur&lt;/code&gt; function we check to see if &lt;code&gt;y&lt;/code&gt; is greater than zero, and if it is we modify the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; values (like we did in the previous example) and then return another reference to the &lt;code&gt;recur&lt;/code&gt; function but this time with the modified &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; values.&lt;/li&gt;&#xA;&lt;li&gt;Inside the &lt;code&gt;trampoline&lt;/code&gt; function the newly referenced function is assigned to the &lt;code&gt;f&lt;/code&gt; variable and the &lt;code&gt;while&lt;/code&gt; loop on its next iteration checks to see if &lt;code&gt;f&lt;/code&gt; is indeed a function or not. If it is (which it would be in this instance) we again execute the function (which is now &lt;code&gt;recur(2, 9)&lt;/code&gt;) and the whole process starts again.&lt;/li&gt;&#xA;&lt;li&gt;Until of course we reach the point where &lt;code&gt;y&lt;/code&gt; is set to zero. Then when the &lt;code&gt;trampoline&lt;/code&gt; function executes the function reference (&lt;code&gt;recur&lt;/code&gt;) and inside the &lt;code&gt;if&lt;/code&gt; conditional fails (as &lt;code&gt;y&lt;/code&gt; is now zero and no longer greater than zero) and so we return the accumulated &lt;code&gt;x&lt;/code&gt; value; which then gets sent back and stored in the &lt;code&gt;f&lt;/code&gt; variable inside the &lt;code&gt;trampoline&lt;/code&gt; function.&lt;/li&gt;&#xA;&lt;li&gt;On the next iteration of the &lt;code&gt;while&lt;/code&gt; loop, &lt;code&gt;f&lt;/code&gt; is now a value and not a function and so the &lt;code&gt;while&lt;/code&gt; loop ends and the accumulated value is returned to the &lt;code&gt;sum&lt;/code&gt; function which returns that as its accumulated value.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;a-more-advanced-solution&#34;&gt;A more advanced solution&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The previous code we just looked at works fine, but it required us to modify our code to work with the &amp;lsquo;trampoline&amp;rsquo; pattern. This is a bit of a pain and means if we have lots of recursive code then it means each one might need subtle changes to accommodate this pattern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code is an abstraction around that concept and it&amp;rsquo;ll allow us to keep our code exactly the same, with no modifications, and the abstraction will handle all of the work for us!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s take a look at the implementation&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function tco(f) {&#xA;    var value;&#xA;    var active = false;&#xA;    var accumulated = [];&#xA;&#xA;    return function accumulator() {&#xA;        accumulated.push(arguments);&#xA;&#xA;        if (!active) {&#xA;            active = true;&#xA;&#xA;            while (accumulated.length) {&#xA;                value = f.apply(this, accumulated.shift());&#xA;            }&#xA;&#xA;            active = false;&#xA;&#xA;            return value;&#xA;        }&#xA;    }&#xA;}&#xA;&#xA;var sum = tco(function(x, y) {&#xA;    if (y &amp;gt; 0) {&#xA;      return sum(x + 1, y - 1)&#xA;    }&#xA;    else {&#xA;      return x&#xA;    }&#xA;});&#xA;&#xA;sum(1, 100000) // =&amp;gt; 100001&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here we&amp;rsquo;ve written a &lt;code&gt;tco&lt;/code&gt; function which simply wraps around our original code (so no modification required to our code).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s now take a look at how it works.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;explanation&#34;&gt;Explanation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Be warned that understanding this code &lt;em&gt;could&lt;/em&gt; take a while (lord knows it took me long enough to figure it out; that&amp;rsquo;s what prompted me to write this post, so I wouldn&amp;rsquo;t forget!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t understand how the code works after the first time reading through these notes then it&amp;rsquo;s probably best to execute the above code via your browser of choice&amp;rsquo;s developer tools and use a &lt;code&gt;debugger&lt;/code&gt; statement to step through the code whilst reading this explanation&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the above code was written by Irakli Gozalishvili (an engineer at Mozilla): &lt;a href=&#34;https://gist.github.com/Gozala/1697037&#34; target=&#34;_blank&#34;&gt;https://gist.github.com/Gozala/1697037&lt;/a&gt;. As you can see above, it makes tail call optimising any function really easy.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We store the result of calling &lt;code&gt;tco&lt;/code&gt; (wrapped around our code) into the &lt;code&gt;sum&lt;/code&gt; variable.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;sum&lt;/code&gt; variable is now a function expression that when called (e.g. &lt;code&gt;sum(1, 10)&lt;/code&gt;) will execute the &lt;code&gt;accumulator&lt;/code&gt; function that &lt;code&gt;tco&lt;/code&gt; returned.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;accumulator&lt;/code&gt; is a closure (meaning when we call &lt;code&gt;sum&lt;/code&gt; the &lt;code&gt;accumulator&lt;/code&gt; will have access to the variables defined inside of &lt;code&gt;tco&lt;/code&gt; -&amp;gt; &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;active&lt;/code&gt; and &lt;code&gt;accumulated&lt;/code&gt;; as well as our own code which is accessible via the identifier &lt;code&gt;f&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;When we call &lt;code&gt;sum&lt;/code&gt; for the first time (e.g. &lt;code&gt;sum(1, 10)&lt;/code&gt;) we indirectly execute &lt;code&gt;accumulator&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;The first thing we do inside of &lt;code&gt;accumulator&lt;/code&gt; is push the arguments object (an Array-like object) into the &lt;code&gt;accumulated&lt;/code&gt; Array (so the &lt;code&gt;accumulated&lt;/code&gt; will now have a length of 1).&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s worth knowing that the &lt;code&gt;accumulated&lt;/code&gt; Array only ever has 1 item inside of it (as we&amp;rsquo;ll soon see).&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;active&lt;/code&gt; variable by default is &lt;code&gt;false&lt;/code&gt;. So as &lt;code&gt;accumulator&lt;/code&gt; is called for the first time, we end up inside the &lt;code&gt;if&lt;/code&gt; conditional, and then reset &lt;code&gt;active&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Now we get to a &lt;code&gt;while&lt;/code&gt; loop (we&amp;rsquo;re still calling functions recursively, as you&amp;rsquo;ll see in a moment; but this is a very clean loop compared to an ugly for loop with lots of operators/operands).&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;while&lt;/code&gt; loop simply checks whether the &lt;code&gt;accumulated&lt;/code&gt; Array has any content. If it does then we call the &lt;code&gt;f&lt;/code&gt; function and pass through the arguments that were inside &lt;code&gt;accumulated[0]&lt;/code&gt; (for the first run of this function that would&amp;rsquo;ve been &lt;code&gt;[1, 10]&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;When we pass the contents of &lt;code&gt;accumulated[0]&lt;/code&gt; we use the &lt;code&gt;shift&lt;/code&gt; Array method to actually remove it from the &lt;code&gt;accumulated&lt;/code&gt; Array so it now has a length of zero.&lt;/li&gt;&#xA;&lt;li&gt;If we ignore for a moment the code inside the loop; on the next iteration of this loop the condition of &lt;code&gt;accumulated.length&lt;/code&gt; will fail and so we would end up setting &lt;code&gt;active&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; and ultimately return to &lt;code&gt;sum&lt;/code&gt; the value of the variable &lt;code&gt;value&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;This is where it gets confusing, but hold tight!&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;f&lt;/code&gt; function is our own code. Our own code calls the &lt;code&gt;sum&lt;/code&gt; function (which indirectly calls the &lt;code&gt;accumulator&lt;/code&gt; function).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The secret sauce to this entire chunk of code is coming up!&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If our code returns &lt;code&gt;x&lt;/code&gt; then the &lt;code&gt;while&lt;/code&gt; loop will stop (I&amp;rsquo;ll explain why in a moment).&lt;/li&gt;&#xA;&lt;li&gt;If our code can&amp;rsquo;t return &lt;code&gt;x&lt;/code&gt; (notice our code has a conditional check to see if &lt;code&gt;y&lt;/code&gt; is greater than zero, if it is then we return &lt;code&gt;x&lt;/code&gt;, otherwise&amp;hellip;) we call &lt;code&gt;sum&lt;/code&gt; again and pass through modified arguments.&lt;/li&gt;&#xA;&lt;li&gt;This time when we call &lt;code&gt;sum&lt;/code&gt; we don&amp;rsquo;t get inside of the &lt;code&gt;if&lt;/code&gt; conditional because &lt;code&gt;active&lt;/code&gt; is already set to &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;So the purpose of calling &lt;code&gt;sum&lt;/code&gt; from inside our own code is simply to allow us to store the newly modified arguments inside the &lt;code&gt;accumulated&lt;/code&gt; Array.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;sum&lt;/code&gt; function then returns &lt;code&gt;undefined&lt;/code&gt; (as we weren&amp;rsquo;t able to move into the &lt;code&gt;if&lt;/code&gt; conditional)&lt;/li&gt;&#xA;&lt;li&gt;The flow of control then throws us back into the original &lt;code&gt;while&lt;/code&gt; loop (that&amp;rsquo;s still going, it hasn&amp;rsquo;t stopped yet) and &lt;code&gt;undefined&lt;/code&gt; is what&amp;rsquo;s stored into the &lt;code&gt;value&lt;/code&gt; variable.&lt;/li&gt;&#xA;&lt;li&gt;At this point the &lt;code&gt;accumulated&lt;/code&gt; Array has once again got some content and so the &lt;code&gt;while&lt;/code&gt; loop&amp;rsquo;s condition passes once more.&lt;/li&gt;&#xA;&lt;li&gt;And &lt;em&gt;that&lt;/em&gt; is where the recursive magic happens. At some point our code is going to call &lt;code&gt;sum&lt;/code&gt; with the &lt;code&gt;y&lt;/code&gt; argument set to zero meaning that when the &lt;code&gt;accumulator&lt;/code&gt; function calls our code the condition &lt;code&gt;y &amp;gt; 0&lt;/code&gt; will fail and so we return the value of &lt;code&gt;x&lt;/code&gt; (which has been incremented each time along the way).&lt;/li&gt;&#xA;&lt;li&gt;When that happens, &lt;code&gt;x&lt;/code&gt; is returned and assigned as the value to the &lt;code&gt;value&lt;/code&gt; variable, and so our code never called &lt;code&gt;sum&lt;/code&gt; and thus the &lt;code&gt;accumulated&lt;/code&gt; Array is never modified again; meaning the &lt;code&gt;while&lt;/code&gt; loop condition inside the &lt;code&gt;accumulator&lt;/code&gt; function will fail and thus the &lt;code&gt;accumulator&lt;/code&gt; function will end returning whatever value is stored inside the &lt;code&gt;value&lt;/code&gt; variable (which in this example is the value of &lt;code&gt;x&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There you have it, a quick run through of TCO, what it means and how potentially to work around it in JavaScript. Go forth and be productive!&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;update-1&#34;&gt;Update 1&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve since discovered a nice explanation of trampolining in the JS Drip Newsletter (#65).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code is an example that is NOT tail-call optimised:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function isEvenNaive (num) {&#xA;    if (num === 0) {&#xA;        return true;&#xA;    }&#xA; &#xA;    if (num === 1) {&#xA;        return false;&#xA;    }&#xA; &#xA;    return isEvenNaive(Math.abs(num) - 2);&#xA;}&#xA; &#xA;isEvenNaive(10);&#xA;// =&amp;gt; true&#xA; &#xA;isEvenNaive(9);&#xA;// =&amp;gt; false&#xA; &#xA;isEvenNaive(99999);&#xA;// =&amp;gt; InternalError: too much recursion&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following code snippet demonstrates the first step towards trampolining, which is to flatten the stack by requiring the user to manually execute the function over and over:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function isEvenInner (num) {&#xA;    if (num === 0) {&#xA;        return true;&#xA;    }&#xA; &#xA;    if (num === 1) {&#xA;        return false;&#xA;    }&#xA; &#xA;    return function() {&#xA;        return isEvenInner(Math.abs(num) - 2);&#xA;    };&#xA;}&#xA; &#xA;isEvenInner(8);&#xA;// =&amp;gt; function() {&#xA;//        return isEvenInner(Math.abs(num) - 2);&#xA;//    };&#xA; &#xA;isEvenInner(8)()()()();&#xA;// =&amp;gt; true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The first thing to notice about our &lt;code&gt;isEvenInner&lt;/code&gt; function is that instead of directly calling itself again, it returns an anonymous function. That means each call to &lt;code&gt;isEvenInner&lt;/code&gt; gets resolved immediately, and doesn&amp;rsquo;t increase the size of the stack. It also means that we need a way to automatically invoke all of those anonymous functions that will get returned along the way. That&amp;rsquo;s where trampoline comes in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The trampoline function effectively turns this recursive algorithm into something that is executed by a &lt;code&gt;while&lt;/code&gt; loop. As long as &lt;code&gt;isEvenInner&lt;/code&gt; keeps returning functions, trampoline will keep executing them. When we finally reach a non-function value, trampoline will return the result.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, finally, let&amp;rsquo;s see an example that automates the execution of the flatterned stack:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function trampoline (func, arg) {&#xA;    var value = func(arg);&#xA; &#xA;    while(typeof value === &amp;quot;function&amp;quot;) {&#xA;        value = value();&#xA;    }&#xA; &#xA;    return value;&#xA;}&#xA; &#xA;trampoline(isEvenInner, 99999);&#xA;// =&amp;gt; false&#xA; &#xA;trampoline(isEvenInner, 99998);&#xA;// =&amp;gt; true&#xA; &#xA;var isEven = trampoline.bind(null, isEvenInner);&#xA; &#xA;isEven(99999);&#xA;// =&amp;gt; false&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/</guid>
      <link>https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/</link>
      <pubDate>Sat, 26 Apr 2014 00:00:00 +0000</pubDate>
      <title>Functional Recursive JavaScript Programming</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s begin by considering: &amp;ldquo;What is Refactoring?&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The definition of refactoring is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behaviour&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Refactoring is a term originated from the &lt;a href=&#34;http://en.wikipedia.org/wiki/Smalltalk&#34; target=&#34;_blank&#34;&gt;Smalltalk&lt;/a&gt; community of developers back in the mid-late nineties.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Two of the most prolific programmers of recent times, &lt;a href=&#34;http://martinfowler.com/&#34; target=&#34;_blank&#34;&gt;Martin Fowler&lt;/a&gt; and &lt;a href=&#34;http://en.wikipedia.org/wiki/Kent_Beck&#34; target=&#34;_blank&#34;&gt;Kent Beck&lt;/a&gt; literally wrote the book on the subject of refactoring called &amp;ldquo;&lt;a href=&#34;http://www.amazon.com/gp/product/0201485672&#34; target=&#34;_blank&#34;&gt;Refactoring: Improving the Design of Existing Code&lt;/a&gt;&amp;rdquo; (well, written by Martin with contributions from Kent).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In 2009 both Martin and Kent helped with a rewrite of the book that focused more on the Ruby language than the original book&amp;rsquo;s target language of Java. This follow-up book was called &amp;ldquo;&lt;a href=&#34;http://www.amazon.com/Refactoring-Ruby-Edition-Jay-Fields/dp/0321603508&#34; target=&#34;_blank&#34;&gt;Refactoring: The Ruby Edition&lt;/a&gt;&amp;rdquo; and it&amp;rsquo;s that book which is the primary driving force of this post.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Since reading the Ruby edition I wanted to have a short summarised version of some of the more commonly used refactoring techniques (mainly for my own reference). By that I mean the techniques described in the book that I find interesting and use a lot in my day to day programming life.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;languages&#34;&gt;Languages&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;These refactoring techniques aren&amp;rsquo;t specific to the Ruby language (although my &lt;em&gt;implementation&lt;/em&gt; examples are). You can use them when working with JavaScript or PHP (or any other language for that matter).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Programming languages don&amp;rsquo;t all offer identical APIs and so sometimes you might need to tweak the examples slightly to fit your environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Regardless, the idioms and syntax differences between languages become redundant when you just focus on the pattern(s) behind the proposed solution.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;why-refactor&#34;&gt;Why refactor?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The purpose of refactoring is to improve the quality, clarity and maintainability of your code. Simple really.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But also, refactoring can be a great lesson in understanding an unfamiliar code base.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think about it, if you inherit a poorly designed code base that you&amp;rsquo;ve not seen before and you now need to either fix a bug or add a new feature, then implementing the code necessary would be a lot easier once you had refactored it to be in a more stable, maintainable and ultimately &amp;lsquo;understandable&amp;rsquo; state.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Otherwise you would be forced to retro fit your new code on top of a poorly designed foundation and that would be the start of a very unhappy relationship.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;when-should-you-refactor&#34;&gt;When should you refactor?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll usually find the time you start refactoring the most is when you are fixing bugs or adding new features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, you typically first need to understand the code that has already been written (regardless of whether it was you who wrote it originally or someone else).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The process of refactoring helps you better understand the code, in preparation for modifying it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But don&amp;rsquo;t fall into the trap of thinking that refactoring is something you set aside time for, or only consider at the start/end of a project. It&amp;rsquo;s not. Refactoring should be done in small chunks throughout the entire life cycle of the project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As the great &lt;a href=&#34;http://www.cleancoder.com/&#34; target=&#34;_blank&#34;&gt;Uncle Bob&lt;/a&gt; once said:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;leave a module in a better state than you found it&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;what this suggests is that refactoring is essential to your daily coding process.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;tests&#34;&gt;Tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before we get started, it&amp;rsquo;s important to mention that you should have tests in place when you&amp;rsquo;re refactoring.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; refactor without tests, but realise that without tests to back you up then you can have no confidence in the refactoring you are implementing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Refactoring can result in substantial changes to the code and architecture but still leave the top layer API the same. So while you&amp;rsquo;re refactoring remember the old adage&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;program to an interface, not an implementation&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;We want to avoid changing a public API where ever possible (as that&amp;rsquo;s one of the tenets of refactoring).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you don&amp;rsquo;t have tests then I recommend you write some (now)&amp;hellip; don&amp;rsquo;t worry, I&amp;rsquo;ll wait.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember, the process of writing tests (even for an application you don&amp;rsquo;t know) will help solidify your understanding and expectations of the code you&amp;rsquo;re about to work on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Code should be tested regularly while refactoring to ensure you don&amp;rsquo;t break anything. Keep the &amp;lsquo;red, green, refactor&amp;rsquo; feedback loop tight. Tests help confirm if your refactoring has worked or not. Without them you&amp;rsquo;re effectively flying blind.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So although I won&amp;rsquo;t explicitly mention it below when discussing the different refactoring techniques, it is implied that on every change to your code you should really be running the relevant tests to ensure no broken code appears.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;refactoring-techniques&#34;&gt;Refactoring Techniques&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are many documented refactoring techniques and I do not attempt to cover them all, as this post would end up becoming a book in itself. So I&amp;rsquo;ve picked what I feel are the most common and useful refactoring techniques and I try my best to explain them in a short and concise way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve put these techniques in order of how you might approach refactoring a piece of code, in a linear, top to bottom order. This is a personal preference and doesn&amp;rsquo;t necessarily represent the best way to refactor.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Final note: with some of the techniques I have provided a basic code example, but to be honest some techniques are so simple they do not need any example. The &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; is one such technique that although really useful and important, providing a code example would be a waste of time and space.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So without further ado, let&amp;rsquo;s begin&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;rename-method&#34;&gt;Rename Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The single most effective and simple refactoring you can implement is to rename a property/attribute, method or object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Renaming identifiers can reduce the need for code comments and nearly always helps to promote greater clarity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll find that renaming things is a fundamental part of other refactoring techniques to aid understanding of the code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This technique relies on giving items a descriptive name to ensure the developer knows at a glance exactly what it does. The following technique &lt;a href=&#34;#introduce-explaining-variable&#34;&gt;Introduce Explaining Variable&lt;/a&gt; is effectively the same.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;introduce-explaining-variable&#34;&gt;Introduce Explaining Variable&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;So here is a technique specifically based around the premise of renaming.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have a complicated expression (for example, you&amp;rsquo;ll typically have a long winded set of conditions within an &lt;code&gt;if&lt;/code&gt; statement) then place that complex expression into a temp variable and give it a descriptive identifier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;unless &amp;quot;This is a String with some CAPS&amp;quot;.scan(/([A-Z])/).empty?&#xA;  puts &amp;quot;capitalised text was found&amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Should be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;caps_not_found = &amp;quot;This is a String with some CAPS&amp;quot;.scan(/([A-Z])/).empty?&#xA;&#xA;unless caps_not_found&#xA;  puts &amp;quot;capitalised text was found&amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: this is the only technique that finds temps (i.e. local variables) acceptable. This is because temps are deemed to be less reusable than methods (due to their very nature being &amp;lsquo;local&amp;rsquo;) and so introducing temps is something that shouldn&amp;rsquo;t be considered lightly. Maybe consider using the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; technique instead before using this particular technique.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, don&amp;rsquo;t worry about performance until you know you have a performance issue to worry about. Developers will always suggest that calling methods is slower than running code inline, but good programming is about readability and maintainability, and extracted methods are not only easier to understand but are much more reusable by other methods.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you are considering using the &lt;a href=&#34;#introduce-explaining-variable&#34;&gt;Introduce Explaining Variable&lt;/a&gt; technique, first decide whether the temp would be more useful if it was available to other methods (that way you could use &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; instead and avoid defining a temp altogether).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;inline-temp&#34;&gt;Inline Temp&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Temp variables are a bit of a code smell as they make methods longer and can make the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; more awkward (as you&amp;rsquo;d have to pass through more data to the extracted method).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Inline Temp effectively removes the temp variable altogether by just using the value assigned to it (I&amp;rsquo;d only suggest doing this if the temp is only used once or if the resulting value has come from a method invocation).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def add_stuff&#xA;    1 + 1&#xA;end&#xA;&#xA;def do_something&#xA;    temp_variable_with_descriptive_name = add_stuff&#xA;    puts &amp;quot;Number is #{temp_variable_with_descriptive_name}&amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Should be:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def add_stuff&#xA;    1 + 1&#xA;end&#xA;&#xA;def do_something&#xA;    puts &amp;quot;Number is #{add_stuff}&amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: a temp by itself doesn&amp;rsquo;t do any harm, and in some instances can actually make the code clearer (especially if using a result from a method invocation and the method identifier doesn&amp;rsquo;t indicate the intent as well as it should).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But most likely you&amp;rsquo;ll end up using this technique to aid the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; technique as less temp vars means less requirement to pass through additional parameters to the extracted method.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;split-temp-variable&#34;&gt;Split Temp Variable&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This technique aims to resolve the concern of violating the SRP (Single Responsibility Principle), although slightly tamer in the sense that SRP is aimed more at Classes/Objects and methods, not typically variable assignments.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But regardless if a temporary variable is assigned to more than once and it is not a loop variable or a collecting/accumulator variable then it is a temp considered to have too many responsibilities.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;For example&lt;/strong&gt;: (this is a daft example, but what the heck)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;temp = 2 * (height + width)&#xA;temp = height * width&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Becomes&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;perimeter = 2 * (height + width)&#xA;area = height * width&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, the temp variable was handling more responsibility than it should be and so by creating two appropriately distinct temps we ensure greater code clarity.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-temp-with-query&#34;&gt;Replace Temp With Query&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This technique has a very similar intent to &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt; in that one of its primary focuses is to aid the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The subtle but important difference between this technique and &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt; is that the complex expression assigned to the temp needs to be first moved to a method (whereas the &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt; technique is different in that the temp may already be using a method invocation).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Box&#xA;  attr_reader :length, :width, :height&#xA;&#xA;  def initialize length, width, height&#xA;    @length = length&#xA;    @width  = width&#xA;    @height = height&#xA;  end&#xA;&#xA;  def volume&#xA;    # `area` is the temp&#xA;    area = length * width&#xA;    area * height&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Box&#xA;  attr_reader :length, :width, :height&#xA;&#xA;  def initialize length, width, height&#xA;    @length = length&#xA;    @width  = width&#xA;    @height = height&#xA;  end&#xA;&#xA;  def volume&#xA;    # notice `area` is now a direct method call&#xA;    area * height&#xA;  end&#xA;&#xA;  def area&#xA;    length * width&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This technique can help to shorten a long method by not having to define lots of temp variables just to hold values.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the extracted query method is given an identifier that aptly describes its purpose then the code still can be considered clear and descriptive.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, it is considered bad form to define a variable which changes once it has been set (hence moving to a method better indicates an unstable value).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note: this technique can sometimes be made easier to implement once you&amp;rsquo;ve used &lt;a href=&#34;#split-temp-variable&#34;&gt;Split Temp Variable&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember this technique (as with other techniques) is an incremental step towards removing non-essential temps, so consider using &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt; afterwards, thus removing the need for the temp altogether.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-temp-with-chain&#34;&gt;Replace Temp With Chain&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is yet another technique designed to rid your code of temp variables.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have a temp variable holding the result of calling an object&amp;rsquo;s method, and follow the assignment by using that temp to carry out more method calls, then you should consider chaining method calls instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The implementation is quite simple, you just have to ensure the methods called return &lt;code&gt;self&lt;/code&gt; (or &lt;code&gt;this&lt;/code&gt; if using a language like JavaScript).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By allowing methods to chain we again have the opportunity to remove an unnecessary temps.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;For example&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class College&#xA;    def create_course&#xA;        puts &amp;quot;create course&amp;quot;&#xA;    end&#xA;&#xA;    def add_student&#xA;        puts &amp;quot;add student&amp;quot;&#xA;    end&#xA;end&#xA;&#xA;temp = College.new&#xA;temp.create_course&#xA;temp.add_student&#xA;temp.add_student&#xA;temp.add_student&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Becomes&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class College&#xA;    # static method so can be accessed without creating an instance&#xA;    def self.create_course&#xA;        college = College.new&#xA;        puts &amp;quot;create course&amp;quot;&#xA;        college # return new object instance&#xA;    end&#xA;&#xA;    def add_student&#xA;        puts &amp;quot;add student&amp;quot;&#xA;        self # refers to the new object instance&#xA;    end&#xA;end&#xA;&#xA;college = College.create_course&#xA;                 .add_student&#xA;                 .add_student&#xA;                 .add_student&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;extract-method&#34;&gt;Extract Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here it is! In my opinion &amp;lsquo;&lt;em&gt;The&lt;/em&gt;&amp;rsquo; most used and important refactoring technique.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The implementation behind this technique is very simple. It consists of breaking up long methods by shifting overly complex chunks of code into new methods which have very descriptive identifiers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  attr_reader :bar&#xA;&#xA;  def initialize bar&#xA;    @bar = bar&#xA;  end&#xA;&#xA;  def do_something&#xA;    puts &amp;quot;my baz&amp;quot; # notice this is duplication&#xA;    puts bar&#xA;  end&#xA;&#xA;  def do_something_else&#xA;    puts &amp;quot;my baz&amp;quot; # notice this is duplication&#xA;    puts &amp;quot;Something else&amp;quot;&#xA;    puts bar&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  attr_reader :bar&#xA;&#xA;  def initialize bar&#xA;    @bar = bar&#xA;  end&#xA;&#xA;  def do_something&#xA;    baz&#xA;    puts bar&#xA;  end&#xA;&#xA;  def do_something_else&#xA;    baz&#xA;    puts &amp;quot;Something else&amp;quot;&#xA;    puts bar&#xA;  end&#xA;&#xA;  def baz&#xA;    puts &amp;quot;my baz&amp;quot;&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But be careful with handling local variables as you&amp;rsquo;ll need to pass them through to the extracted method and that can be difficult if there are lots of temps in use. Sometimes to facility the Extract Method you&amp;rsquo;ll need to first incorporate other techniques such as &lt;a href=&#34;#replace-temp-with-query&#34;&gt;Replace Temp With Query&lt;/a&gt; and &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;inline-method&#34;&gt;Inline Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes you want the opposite of the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; technique. Imagine a method exists whose content is already simple and clear, and whose identifier adds no extra benefit. In this instance we&amp;rsquo;re just making an extra call for no real benefit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So to fix this problem we&amp;rsquo;ll convert the method invocation into an inlined piece of code (unless of course the method is used in multiple places, in that case leave it where it is as having it in a separate method keeps our code DRY).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;move-method&#34;&gt;Move Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In a previous post about &lt;a href=&#34;/posts/design-oop/#class-analysis&#34;&gt;Object-Oriented Design&lt;/a&gt; I explained that you should query your classes/objects to ensure the methods they define are actually where they should be (another reason is &amp;lsquo;feature envy&amp;rsquo;, if a method is asking another class a lot of questions then it may be an indication the method is on the wrong object).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Move Method technique ensures this decoupling by simply moving the identified misplaced method onto the correct one.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once the method has been moved you should clean up the previously passed parameters by seeing what can be moved over to the other object or whether additional data needs to be passed over now via the method invocation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Gear&#xA;    attr_reader :chainring, :cog, :rim, :tire&#xA;&#xA;    def initialize (chainring, cog, rim, tire)&#xA;      @chainring = chainring&#xA;      @cog       = cog&#xA;      @rim       = rim&#xA;      @tire      = tire&#xA;&#xA;      # let&#39;s asked the question:&#xA;      # &amp;quot;Please Mr. Gear what is your tire size?&amp;quot;&#xA;      # hmm? notice this doesn&#39;t sound like it quite fits the purpose of a &#39;Gears&#39; class&#xA;    end&#xA;&#xA;    def ratio&#xA;      chainring / cog.to_f&#xA;    end&#xA;&#xA;    def gear_inches&#xA;        # tire goes around rim twice for diameter&#xA;        ratio * (rim + (tire * 2))&#xA;    end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Gear&#xA;    attr_reader :chainring, :cog, :rim, :tire&#xA;&#xA;    def initialize (chainring, cog, rim, tire)&#xA;      @chainring = chainring&#xA;      @cog       = cog&#xA;      @rim       = rim&#xA;      @tire      = tire.size&#xA;    end&#xA;&#xA;    def ratio&#xA;      chainring / cog.to_f&#xA;    end&#xA;&#xA;    def gear_inches&#xA;        # tire goes around rim twice for diameter&#xA;        ratio * (rim + (tire * 2))&#xA;    end&#xA;end&#xA;&#xA;class Tire&#xA;  def self.size&#xA;    5&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From the original class/object keep the original method in place while you test and change it so it now delegates to the method on the new object. Then slowly refactor by replacing delegating calls throughout your code base with direct calls to the method via its new host.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, remove the old method altogether and the tests should tell you if you missed a replacement somewhere.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-method-with-method-object&#34;&gt;Replace Method With Method Object&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You may run into a problem where you have a long method you want to use &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; on, but the number of temporary local variables are too great to allow you to utilise the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; technique (because passing around that many variables would be just as messy as the long method itself).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To resolve this issue you could look at different types of smaller refactors (such as &lt;a href=&#34;#inline-temp&#34;&gt;Inline Temp&lt;/a&gt;) but in some cases it would actually be better to first move the contents of the long method into an entirely new object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the first thing to do is create a new class named after the long method and add the temp local vars as properties/attributes of the class/object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now when you try to implement &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; you don&amp;rsquo;t have to pass around the temp vars because they are now available throughout the class/object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then from within the original class/object you can delegate any calls to the original method on to the object (you&amp;rsquo;ll still pass on the original arguments to the method within the new object but from there on the method extraction becomes easier).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  def bar&#xA;    puts &amp;quot;We&#39;re doing some bar stuff&amp;quot;&#xA;  end&#xA;&#xA;  def baz(a, b, c)&#xA;    if a == &#39;something&#39;&#xA;      # do something&#xA;    end&#xA;&#xA;    if b == &#39;else&#39;&#xA;      # do else&#xA;    end&#xA;&#xA;    if c == &#39;none&#39;&#xA;      # do none&#xA;    end&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  def bar&#xA;    puts &amp;quot;We&#39;re doing some bar stuff&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class Baz&#xA;  attr_accessor :a, :b, :c&#xA;&#xA;  def initialize(a, b, c)&#xA;    @a = a&#xA;    @b = b&#xA;    @c = c&#xA;&#xA;    if a == &#39;something&#39;&#xA;      # do something&#xA;    end&#xA;&#xA;    if b == &#39;else&#39;&#xA;      # do else&#xA;    end&#xA;&#xA;    if c == &#39;none&#39;&#xA;      # do none&#xA;    end&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;From here we&amp;rsquo;re now in a better state to use both the &lt;a href=&#34;#extract-method&#34;&gt;Extract Method&lt;/a&gt; and &lt;a href=&#34;/posts/refactoring-techniques/#replace-conditional-with-polymorphism&#34;&gt;Replace Conditional with Polymorphism&lt;/a&gt; techniques to refactor the &lt;code&gt;Baz&lt;/code&gt; class.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-loop-with-collection-closure-method&#34;&gt;Replace Loop With Collection Closure Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you write a loop that parses a collection and interacts with the individual elements within the collection then move that interaction out into a separate closure based method (meaning you replace the loop with an Enumerable method).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This refactoring may not be as clear or impressive as other refactoring techniques but the motivation behind it is that you hide the ugly details of the loop behind a nicer iteration method, allowing the developer looking at the code to focus on the business logic instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;For example&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;managers = []&#xA;employees.each do |e|&#xA;    managers &amp;lt;&amp;lt; e if e.manager?&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Becomes&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;managers = employees.select { |e| e.manager? }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Ruby has a few of these types of enumerable methods but other languages such as PHP and JavaScript aren&amp;rsquo;t so lucky.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;JavaScript has a couple of accumulators: &lt;code&gt;Array#reduce&lt;/code&gt; and &lt;code&gt;Array#reduceRight&lt;/code&gt; but they aren&amp;rsquo;t very useful as closure based collection methods compared to Ruby which has methods such as &lt;code&gt;Enumerable#inject&lt;/code&gt;, &lt;code&gt;Enumerable#select&lt;/code&gt; (seen in above example) or &lt;code&gt;Enumerable#collect&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note: in JavaScript you can implement a similar effect with clever use of closures.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;pull-up-method&#34;&gt;Pull Up Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When you have duplicated code across two separate classes then the best refactoring technique to implement is to pull that duplicate code up into a super class so we DRY (Don&amp;rsquo;t Repeat Yourself) out the code and allow it to be used in multiple places without duplication (meaning changes in future only have to happen in one place).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Person&#xA;  attr_reader :first_name, :last_name&#xA;&#xA;  def initialize first_name, last_name&#xA;    @first_name = first_name&#xA;    @last_name = last_name&#xA;  end&#xA;&#xA;end&#xA;&#xA;class MalePerson &amp;lt; Person&#xA;  # This is duplicated in the `FemalePerson` class&#xA;  def full_name&#xA;    first_name + &amp;quot; &amp;quot; + last_name&#xA;  end&#xA;&#xA;  def gender&#xA;    &amp;quot;M&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class FemalePerson &amp;lt; Person&#xA;  # This is duplicated in the `MalePerson` class&#xA;  def full_name&#xA;    first_name + &amp;quot; &amp;quot; + last_name&#xA;  end&#xA;&#xA;  def gender&#xA;    &amp;quot;F&amp;quot;&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Person&#xA;  attr_reader :first_name, :last_name&#xA;&#xA;  def initialize first_name, last_name&#xA;    @first_name = first_name&#xA;    @last_name = last_name&#xA;  end&#xA;&#xA;  def full_name&#xA;    first_name + &amp;quot; &amp;quot; + last_name&#xA;  end&#xA;end&#xA;&#xA;class MalePerson &amp;lt; Person&#xA;  def gender&#xA;    &amp;quot;M&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class FemalePerson &amp;lt; Person&#xA;  def gender&#xA;    &amp;quot;F&amp;quot;&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;form-template-method&#34;&gt;Form Template Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The technique is reliant on inheritance: a parent class and two sub classes of&#xA;that parent. The two sub classes have methods which have similar steps, in the&#xA;same order and yet the steps themselves are different.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The technique involves moving the sequence of steps into the parent class and&#xA;then using polymorphism to allow the sub classes to handle the differences in&#xA;the steps.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a silly example (I’m no good at giving real examples; you may have noticed), here is an&#xA;example of our problematic code…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo; end&#xA;&#xA;class Bar &amp;lt; Foo&#xA;  def initialize&#xA;    @hey = 1&#xA;    @hai = 2&#xA;  end&#xA;&#xA;  def qux&#xA;    @a = @hey + @hai&#xA;    @b = @a * 10&#xA;    @a + @b&#xA;  end&#xA;end&#xA;&#xA;class Baz &amp;lt; Foo&#xA;  def initialize&#xA;    @hey = 5&#xA;    @hai = 7&#xA;  end&#xA;&#xA;  def qux&#xA;    @a = @hey + @hai&#xA;    @b = @a * 10 * 20&#xA;    @a + @b&#xA;  end&#xA;end&#xA;&#xA;bar = Bar.new&#xA;baz = Baz.new&#xA;&#xA;puts bar.qux&#xA;puts baz.qux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…we could try to inject the values each sub class requires but then we still&#xA;have a lot of duplication in this code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can see the sequence of steps is:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;determine what &lt;code&gt;a&lt;/code&gt; should be&lt;br&gt;&#xA;determine what &lt;code&gt;b&lt;/code&gt; should be&lt;br&gt;&#xA;return a specific calculation&lt;/p&gt;&#xA;&#xA;&lt;p&gt;…so we can clean up our code a little by abstracting the commonality&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  def initialize(hey=1, hai=1)&#xA;    @hey = hey&#xA;    @hai = hai&#xA;  end&#xA;&#xA;  def qux&#xA;    determine_a&#xA;    determine_b&#xA;    result&#xA;  end&#xA;&#xA;  def determine_a&#xA;    @a = @hey + @hai&#xA;  end&#xA;&#xA;  def result&#xA;    @a + @b&#xA;  end&#xA;end&#xA;&#xA;class Bar &amp;lt; Foo&#xA;  protected&#xA;&#xA;  def determine_b&#xA;    @b = @a * 10&#xA;  end&#xA;end&#xA;&#xA;class Baz &amp;lt; Foo&#xA;  protected&#xA;&#xA;  def determine_b&#xA;    @b = @a * 10 * 20&#xA;  end&#xA;end&#xA;&#xA;bar = Bar.new(1, 2)&#xA;baz = Baz.new(5, 7)&#xA;&#xA;puts bar.qux&#xA;puts baz.qux&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;extract-surrounding-method&#34;&gt;Extract Surrounding Method&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you find you have different methods which contain almost identical code but with a slight variant in the middle, then pull up the duplicated code into a single method and pass a code block to the newly created method which it yields to in order to execute the unique behaviour&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def do_something&#xA;    puts 1&#xA;    yield&#xA;    puts 3&#xA;end&#xA;&#xA;do_something { puts 2 }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is actually a common pattern in Ruby known as the &amp;lsquo;wrap around&amp;rsquo; method. This technique is similar to the &lt;a href=&#34;#form-template-method&#34;&gt;Form Template Method&lt;/a&gt;, but is different in that you can use it without forcing an inheritance model on your code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note: JavaScript doesn&amp;rsquo;t have the ability to pass a code block but it can be replicated by passing a function that acts like a callback&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function doSomething (callback) {&#xA;        console.log(1);&#xA;        callback();&#xA;        console.log(3);&#xA;}&#xA;&#xA;doSomething(function(){&#xA;        console.log(2);&#xA;});&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;although in the latest versions of Node (as of November 2013) Generators are implemented and would allow JavaScript code to &lt;code&gt;yield&lt;/code&gt; similar to how Ruby works.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;self-encapsulate-field&#34;&gt;Self Encapsulate Field&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When inheriting properties from a parent class/object then it can be more flexible if the parent class only allows access to the properties from within a getter/setter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The motivation for this technique is that a sub class can override and modify the behaviour of the getter/setter without affecting the parent class&amp;rsquo; implementation. Which is similar to how the Decorator design pattern works (e.g. modifying the behaviour without affecting the original).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This technique should only be used once you find the coupling between objects is becoming a problem. Otherwise direct access to properties and instance variables should be acceptable initially.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def total&#xA;  @base_price * (1 + @tax_rate)&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Becomes:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;attr_reader :base_price, :tax_rate&#xA;&#xA;def total&#xA;  base_price * (1 + tax_rate)&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;introduce-named-parameter&#34;&gt;Introduce Named Parameter&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When method arguments are unclear then convert them into named parameters so they become clearer (and easier to remember).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although Ruby supports named parameters&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def turnOnTheTV (channel: 1, volume: 1); end&#xA;turnOnTheTV(channel: 101, volume: 10)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;neither PHP or JavaScript do, so for PHP you can pass an associated Array and with JavaScript you can pass an Object/Hash.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;For example (JavaScript)&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function turnOnTheTV(c, v){}&#xA;turnOnTheTV(101, 10);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Becomes&lt;/strong&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function turnOnTheTV (config) {&#xA;    // config.channel === 101&#xA;    // config.volume  === 10&#xA;}&#xA;turnOnTheTV({ channel: 101, volume: 10 });&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: ECMAScript 6.0 (the latest JavaScript specification - which is still being worked on as of Nov 2013) implements named parameters.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;remove-redundancy&#34;&gt;Remove Redundancy&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t an explicit technique, more a grouping of techniques.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The principle idea being that: code evolves, and as it evolves you may find techniques you previously implemented (as part of an earlier refactoring) have since become redundant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you implemented the &amp;ldquo;&lt;a href=&#34;refactoring-techniques.html#22&#34; target=&#34;_blank&#34;&gt;Introduce Named Parameter&lt;/a&gt;&amp;rdquo; technique (passing a hash with named properties as a single argument instead of multiple unidentified arguments).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, after some other refactorings have taken place, you discover the method originally refactored is no longer as complex and so your argument hash refactor has been reduced down to just a single named property.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this particular scenario you should remove the named parameter and simply pass a single argument instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This principle applies with other refactoring techniques.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine an earlier refactoring included implementing a default parameter value for a method call. As your code evolves, if you discover you now only ever call the method &lt;em&gt;with&lt;/em&gt; an argument then the default value becomes redundant and makes the code more complex than it needs to be by providing a default value. So just remove the redundant code.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dynamic-method-definition&#34;&gt;Dynamic Method Definition&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes defining multiple methods can be wasteful when functionally they carry out similar steps.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, imagine we had the following code&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def failure do &#xA;  self.result = &amp;quot;failure&amp;quot; &#xA;end &#xA;&#xA;def success do &#xA;  self.result = &amp;quot;success&amp;quot; &#xA;end &#xA;&#xA;def error do &#xA;  self.result = &amp;quot;error&amp;quot; &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice how the functions are structurally identical. They simply set a &lt;code&gt;result&lt;/code&gt; property to have a value&#xA;This can be refactored using Ruby&amp;rsquo;s &lt;code&gt;define_method&lt;/code&gt; method (which let&amp;rsquo;s you create methods dynamically at run time)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[:failure, :success, :error].each do |method| &#xA;  define_method method do &#xA;    self.result = method.to_s &#xA;  end &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: you could also abstract this code into a more reusable (and easier to maintain) function like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def dynamic_methods(*method_names, &amp;amp;block) &#xA;  method_names.each do |method_name| &#xA;    define_method method_name do &#xA;      instance_exec(method_name, &amp;amp;block)&#xA;    end &#xA;  end &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also use this technique to help ease creating properties on an object. For example, I used this technique in my &lt;a href=&#34;/posts/design-mvcp/&#34;&gt;MVCP&lt;/a&gt; blog post to dynamically create instance variables&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;require &#39;app/presenters/base&#39; &#xA;require &#39;app/models/person&#39; &#xA;&#xA;class Presenters::Person &amp;lt; Presenters::Base &#xA;  attr_reader :run, :name, :age &#xA;&#xA;  def initialize &#xA;    @run = true &#xA;&#xA;    model = Person.new(&#39;Mark&#39;, &#39;99&#39;) &#xA;    prepare_view_data({ :name =&amp;gt; model.name, :age =&amp;gt; model.age }) &#xA;  end &#xA;end &#xA;&#xA;module Presenters &#xA;  class Base &#xA;    attr_accessor :model &#xA;&#xA;    def prepare_view_data hash &#xA;      hash.each do |name, value| &#xA;        instance_variable_set(&amp;quot;@#{name}&amp;quot;, value) &#xA;      end &#xA;    end &#xA;  end &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;extract-class&#34;&gt;Extract Class&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is a pretty standard technique which helps ensure your objects abide by the SRP (Single Responsibility Principle).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you find your classes are doing too much then simply create a new class and move the relevant fields and methods over one by one (while running the tests as you go to ensure all code continues working as expected).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Doing so you&amp;rsquo;ll end up with two small, focused and clean classes which are easier to manage.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;hide-delegate&#34;&gt;Hide Delegate&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This technique focuses on the principle of object encapsulation. Specifically decoupling two or more objects by reducing the context the objects have of each other.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code demonstrates the idea&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;module Bar&#xA;  def display&#xA;    puts &amp;quot;Bar Stuff&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;module Baz&#xA;  def display&#xA;    puts &amp;quot;Baz Stuff&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class Foo&#xA;  include Bar&#xA;&#xA;  def do_something&#xA;    display&#xA;  end&#xA;end&#xA;&#xA;foo = Foo.new&#xA;foo.do_something&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;as you can see, the user only needs to rely on the interface having a &lt;code&gt;do_something&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The implementation details of &lt;code&gt;do_somthing&lt;/code&gt; (in this case the delegation off to another method) are hidden.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we changed &lt;code&gt;include Bar&lt;/code&gt; for &lt;code&gt;include Baz&lt;/code&gt;, or maybe we don&amp;rsquo;t mixin a module at all and just write some code inside of &lt;code&gt;do_something&lt;/code&gt;, it doesn&amp;rsquo;t matter because the public interface is set as far as the user is concerned.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-array-with-object&#34;&gt;Replace Array with Object&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The motivation for this technique is to convert a simple data container which holds multiple data types into an object with clear and descriptive identifiers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This principle helps to present your complex data into a more sensible format (I demonstrated this in a previous post on &lt;a href=&#34;/posts/design-oop/#direct-references&#34;&gt;object-oriented design&lt;/a&gt;). This technique also makes the data interaction more maintainable by providing an easier and understandable interface to the data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is an example where we&amp;rsquo;re violating the principle of a clean data interaction&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo &#xA;  attr_reader :data &#xA;&#xA;  def initialize(data) &#xA;    @data = data &#xA;  end &#xA;&#xA;  def do_something &#xA;    data.each do |item| &#xA;      puts item[0] &#xA;      puts item[1] &#xA;      puts &#39;---&#39; &#xA;    end &#xA;  end &#xA;end &#xA;&#xA;obj = Foo.new([[10, 25],[3, 9],[41, 7]]) &#xA;obj.do_something &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice in the first example how our code has far too much knowledge (context) about the object it&amp;rsquo;s interacting with. It knows that the Array index zero holds an X coordinate and the Array index one holds a Y coordinate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If that format was to change (let&amp;rsquo;s say the X and Y swap places) then that would cause our code to break in unexpected ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But now take a look at the following example which works around this issue by converting our complex data structure into a cleaner data format&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo &#xA;  attr_reader :new_data &#xA;&#xA;  def initialize(data) &#xA;    @new_data = transform(data) &#xA;  end &#xA;&#xA;  def do_something &#xA;    new_data.each do |item| &#xA;      # now we are able to reference easily understandable &#xA;      # property names (rather than item[0], item[1]) &#xA;      puts item.coord_x &#xA;      puts item.coord_y &#xA;      puts &#39;---&#39; &#xA;    end &#xA;  end &#xA;&#xA;  Transform = Struct.new(:coord_x, :coord_y) &#xA;&#xA;  def transform(data) &#xA;    data.collect { |item| Transform.new(item[0], item[1]) } &#xA;  end &#xA;end &#xA;&#xA;obj = Foo.new([[10, 25],[3, 9],[41, 7]]) &#xA;obj.do_something &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;here we convert the Array into an object and instead can more easily and safely reference the data we&amp;rsquo;re interested in via recognisable property identifiers. This doesn&amp;rsquo;t mean if the data source changes that we&amp;rsquo;ll totally avoid all problems but it&amp;rsquo;ll be clearer where the problem is arising.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;replace-conditional-with-polymorphism&#34;&gt;Replace Conditional with Polymorphism&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is one of the most useful refactoring techniques available to you, and there are two ways it can help:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;It removes the code smell of conditional logic&lt;/li&gt;&#xA;&lt;li&gt;It demonstrates perfectly the principle of object-oriented design&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;The following example shows the typical procedural attempt to handle different scenarios based on the data object type being passed&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  def initialize(data)&#xA;    @data = data&#xA;  end&#xA;&#xA;  def do_something&#xA;    if @data.class == Bar&#xA;      puts &amp;quot;Bar!&amp;quot;&#xA;    elsif @data.class == Baz&#xA;      puts &amp;quot;Baz!&amp;quot;&#xA;    elsif @data.class == Qux&#xA;      puts &amp;quot;Qux!&amp;quot;&#xA;    end&#xA;  end&#xA;end&#xA;&#xA;class Bar; end&#xA;class Baz; end&#xA;class Qux; end&#xA;&#xA;foo_bar = Foo.new(Bar.new)&#xA;foo_bar.do_something&#xA;&#xA;foo_baz = Foo.new(Baz.new)&#xA;foo_baz.do_something&#xA;&#xA;foo_qux = Foo.new(Qux.new)&#xA;foo_qux.do_something&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;as you can see, if we have a new Class type we need to go back and to modify the &lt;code&gt;Foo&lt;/code&gt; base class. This violates the OCP (Open/Closed Principle) which states a file should be open for extension but closed for modification.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For us to abide by OCP we can use polymorphism and a trusted interface/duck typing to solve the problem&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Foo&#xA;  def initialize(data)&#xA;    @data = data&#xA;  end&#xA;&#xA;  def do_something&#xA;    @data.identifier&#xA;  end&#xA;end&#xA;&#xA;class Bar&#xA;  def identifier&#xA;    puts &amp;quot;#{self.class}!&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class Baz&#xA;  def identifier&#xA;    puts &amp;quot;#{self.class}!&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;class Qux&#xA;  def identifier&#xA;    puts &amp;quot;#{self.class}!&amp;quot;&#xA;  end&#xA;end&#xA;&#xA;foo_bar = Foo.new(Bar.new)&#xA;foo_bar.do_something&#xA;&#xA;foo_baz = Foo.new(Baz.new)&#xA;foo_baz.do_something&#xA;&#xA;foo_qux = Foo.new(Qux.new)&#xA;foo_qux.do_something&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Notice we have removed the need for a conditional and just sent the message to the relevant object to be handled. Much cleaner and easier to maintain and scale.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;decompose-conditional&#34;&gt;Decompose Conditional&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Not all conditional statements can be avoided through the use of polymorphism. In those cases you can simplify the conditional logic (and the subsequent statements) by &lt;a href=&#34;/posts/refactoring-techniques/#extract-method&#34;&gt;extracting them into external methods&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a simple example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if date &amp;lt; SUMMER_START || date &amp;gt; SUMMER_END &#xA;  charge = # some complex calculation if it&#39;s winter &#xA;else &#xA;  charge = # some other complex calculation if it&#39;s summer &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;which we can refactor like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if not_summer(date) &#xA;  charge = winter_charge &#xA;else &#xA;  charge = summer_charge &#xA;end &#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;much better.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;introduce-null-object&#34;&gt;Introduce Null Object&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The motivation behind this technique is to avoid using a conditional whose purpose is to check whether a property exists or not before using it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a simple example of what we want to avoid&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Post&#xA;  attr_reader :id&#xA;&#xA;  def initialize id&#xA;    @id        = id&#xA;    @published = false&#xA;  end&#xA;&#xA;  def self.find_and_publish id&#xA;    # Simulated database operation&#xA;    post = Posts.find { |post| post.id == id }&#xA;    post.publish unless post.nil?&#xA;  end&#xA;&#xA;  def publish&#xA;    puts @published = true&#xA;  end&#xA;end&#xA;&#xA;Posts = [Post.new(1), Post.new(2)]&#xA;&#xA;Post.find_and_publish(0) # displays nothing&#xA;Post.find_and_publish(1) # displays true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;in the above example we check whether &lt;code&gt;post&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; or not. If it isn&amp;rsquo;t &lt;code&gt;nil&lt;/code&gt; then we call the &lt;code&gt;publish&lt;/code&gt; method, otherwise we don&amp;rsquo;t do anything.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is kind of ugly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following code demonstrates how we can avoid that problem by introducing the concept of having an object to handle null scenarios (it&amp;rsquo;s the same principle of using duck typing/trusted interfaces/polymorphism)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Post&#xA;  attr_reader :id&#xA;&#xA;  def initialize id&#xA;    @id        = id&#xA;    @published = false&#xA;  end&#xA;&#xA;  def self.find_and_publish id&#xA;    # Simulated database operation&#xA;    post = Posts.find { |post| post.id == id } || NullPost.new&#xA;    post.publish&#xA;  end&#xA;&#xA;  def publish&#xA;    puts @published = true&#xA;  end&#xA;end&#xA;&#xA;class NullPost&#xA;  def publish&#xA;    # noop&#xA;  end&#xA;end&#xA;&#xA;Posts = [Post.new(1), Post.new(2)]&#xA;&#xA;Post.find_and_publish(0) # displays nothing&#xA;Post.find_and_publish(1) # displays true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;as you can see, effectively we have the same code with the exception that we no longer check for &lt;code&gt;nil?&lt;/code&gt; in the second example and instead we rely on another object &lt;code&gt;NullPost&lt;/code&gt; implementing the same interface but returns a null related value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This way we&amp;rsquo;re using objects to handle our logic. Yes, we end up with more code (one extra Class) but ultimately this is more maintainable and understandable than lots of inline logic.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are still many different refactoring techniques that I&amp;rsquo;ve not included. But hopefully you&amp;rsquo;ve found this quick reference useful so far.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/refactoring-techniques/</guid>
      <link>https://www.integralist.co.uk/posts/refactoring-techniques/</link>
      <pubDate>Sun, 10 Nov 2013 00:00:00 +0000</pubDate>
      <title>Refactoring Techniques</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Model, View, Controller (MVC). This is a pretty standard architectural pattern and has been in use when developing software since the early 1970&amp;rsquo;s.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The basic principle of the pattern is to separate the different areas of logic from your application into distinct compartments.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;model&#34;&gt;Model&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The model holds your business data. Typically this will be data that is pulled in from a database or external data service of some kind.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;view&#34;&gt;View&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The view is your user interface. This is what the client will interact with when using your application.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;controller&#34;&gt;Controller&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The controller is the boss. He sits at the top and delegates responsibilities to either the view or the model.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mixed-definitions&#34;&gt;Mixed definitions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There seems to be a dispute in the dev community regarding how the responsibilities should be divided.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some feel a &amp;lsquo;fat controller&amp;rsquo; principle is best (where by the controller tells the model not only &lt;em&gt;when&lt;/em&gt; but &lt;em&gt;where&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt; it should get its data).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My understanding of the pattern is that it was designed so that the Controller stays &amp;lsquo;skinny&amp;rsquo;. It may be the boss, but like most good bosses it doesn&amp;rsquo;t try and stay in control. It knows the best team member for the job at hand and delegates accordingly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is also good code design because the Controller doesn&amp;rsquo;t have too much &lt;em&gt;context&lt;/em&gt; (i.e. it doesn&amp;rsquo;t know everything, which means it&amp;rsquo;ll be easier to maintain and scale).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;god-controller&#34;&gt;God Controller&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There are a few ways we can implement an MVC pattern, one is known as the &amp;lsquo;God Controller&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where a single Controller exists and it oversees everything no matter what was requested by the client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, the single Controller would be passed the request from the client (usually handled by a custom routing application, and most frameworks will provide their own).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Controller would determine what type of request was made (if the request was for a &amp;lsquo;contact&amp;rsquo; page then it&amp;rsquo;ll make a request for the Contact model, or if the request was for the &amp;lsquo;about&amp;rsquo; page then it&amp;rsquo;ll make a request for the About model).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once it knows the type of request it&amp;rsquo;ll proceed to get the relevant model data and assign it to some View variables and render the required View.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;problems&#34;&gt;Problems&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now there are two problems with this implementation:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;maintainability&lt;/li&gt;&#xA;&lt;li&gt;scalability&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;As mentioned before, this comes down to bad code design. The &amp;lsquo;God Controller&amp;rsquo; knows too much and tries to do too much. Once you start getting above a few different types of requests you&amp;rsquo;ll start to understand what a mess the code can become by having multiple branches for different routing scenarios.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I work as an engineer for the BBC News team in London and we had suffered from this exact set-up (hence the lessons the team has learnt and improved upon are the reason why I&amp;rsquo;m able to write this post for you now).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;skinny-controller&#34;&gt;Skinny Controller&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is another approach we can take which is known as the &amp;lsquo;skinny controller&amp;rsquo; approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way it works is that a request will come into the application and will get passed to a page specific Controller.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The page specific Controller will call the relevant Model and will assign the returned data to a few View variables.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Controller will then render a View and pass through the variables into the View for it to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As you can see, this isn&amp;rsquo;t that different from the &amp;lsquo;God Controller&amp;rsquo; with the exception that the Routing part of the application now will have extra logic which determines which specific Controller should be loaded. This is a better situation to be in because you&amp;rsquo;re making your code base both more maintainable and scalable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note: as I mentioned in the previous section, BBC News had a sort of &amp;lsquo;God Controller&amp;rsquo; issue and our first step to resolving the problem was to take a similar approach as described above (i.e. to start creating page specific Controllers). That was a good first step.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next step from here was to separate out our logic even further by implementing Presenters, and it was our tech lead at BBC News (&lt;a href=&#34;http://twitter.com/jcleveley&#34; target=&#34;_blank&#34;&gt;John Cleveley&lt;/a&gt;) who made that decision which resulted in a much more efficient, maintainable and scalable code base.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;presenters&#34;&gt;Presenters&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;what-problem-are-presenters-trying-to-solve&#34;&gt;What problem are Presenters trying to solve?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine we&amp;rsquo;ve gone for the &amp;lsquo;Skinny Controller&amp;rsquo; approach. There are still some inherent issues…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;First of all, our Controller can still have too much context and be handling more information than it should.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But also, and more importantly, you may find there is still a lot of duplication of code across your Controllers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reasoning for this is that if you consider the structure of a web page/application you&amp;rsquo;ll notice that it is typically made up of unique &amp;lsquo;features&amp;rsquo;. For example, if you&amp;rsquo;re displaying your tweets on a page then that&amp;rsquo;s a unique feature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each feature must be able to stand on its own. We normally describe these features as being &amp;lsquo;components&amp;rsquo;. Each component can be loaded whenever and wherever needed. Having a component based architecture allows your code base to become more modular and reusable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example the navigation menu on a page could be considered a &amp;lsquo;component&amp;rsquo;. Also, the navigation menu component is likely going to need to appear on every single page of the application.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, if you&amp;rsquo;re splitting up your logic into page specific Controllers then it&amp;rsquo;s possible that you&amp;rsquo;re still repeating code across the Controllers to handle the loading of re-occurring components such as the navigation (e.g. pulling its data from a navigation Model and setting View variables etc).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now there are ways that this code repetition can be avoided, and one such way is to use the concept of Presenters.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-do-they-work&#34;&gt;How do they work?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Presenters (like everything in software engineering) can be implemented in many different ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, at BBC News we initially were manually creating new Presenter instances within our page Controllers. But the team here are quite clever chaps (especially &lt;a href=&#34;http://twitter.com/kenturamon&#34; target=&#34;_blank&#34;&gt;Robert Kenny&lt;/a&gt; and &lt;a href=&#34;http://twitter.com/sthulb&#34; target=&#34;_blank&#34;&gt;Simon Thulbourn&lt;/a&gt;) and they realised that this process could be greatly improved by using configuration files instead (specifically &lt;a href=&#34;http://yaml.org/&#34; target=&#34;_blank&#34;&gt;YAML&lt;/a&gt;). As we have multiple teams working on the BBC News code base and in multiple languages, using configuration files is a much easier and maintainable solution.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;m not going to go into the configuration set-up we use at BBC News. Instead I&amp;rsquo;ll focus on the basic principles of how Presenters work, which is quite simply a case of moving the logic (getting component specific Model data and assigning it to to component specific variables) into separate files called Presenters which you can instantiate within your controller.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;code-example&#34;&gt;Code Example&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;controller-1&#34;&gt;Controller&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here is a basic example in Ruby…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;require &#39;app/presenters/a&#39;&#xA;require &#39;app/presenters/b&#39;&#xA;&#xA;class AboutController &amp;lt; ApplicationController&#xA;  get &#39;/&#39; do&#xA;    @a = Presenters::A.new&#xA;    @b = Presenters::B.new&#xA;&#xA;    title &#39;About&#39;&#xA;    erb :about&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…in this example we have an &amp;lsquo;About&amp;rsquo; page which is made up of two components &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;. As you can see we &lt;code&gt;require&lt;/code&gt; the presenters which handle those two components and within our Controller we instantiate the Presenters.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice that&amp;rsquo;s all we do. Each Presenter encapsulates the logic needed to prepare the data to be passed to the &lt;code&gt;:about&lt;/code&gt; view template.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;view-1&#34;&gt;View&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Before I show you the Presenter code itself, I&amp;rsquo;ll show you the View template file…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&amp;lt;%= @title %&amp;gt;&amp;lt;/h1&amp;gt;&#xA;&#xA;&amp;lt;% if @a.run %&amp;gt;&#xA;  &amp;lt;%= partial :&amp;quot;components/a&amp;quot;, { :title =&amp;gt; @a.title, :summary =&amp;gt; @a.summary, :data =&amp;gt; @a.data } %&amp;gt;&#xA;&amp;lt;% end %&amp;gt;&#xA;&#xA;&amp;lt;% if @b.run %&amp;gt;&#xA;  &amp;lt;%= partial :&amp;quot;components/b&amp;quot;, { :name =&amp;gt; @b.name, :age =&amp;gt; @b.age } %&amp;gt;&#xA;&amp;lt;% end %&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…as you can see we have very minimal logic in place. If anything I have too much logic in the View as I initially was re-using the same View template over and over and so I wanted to protect again errors appearing when loading a template which referenced a component I wasn&amp;rsquo;t loading, but I&amp;rsquo;ve since changed how my application was working but left the conditional checks in as an example of how code can evolve over time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We literally just check to see if the component has been initialised (in this case we created a &lt;code&gt;run&lt;/code&gt; property we set to &lt;code&gt;true&lt;/code&gt; when the component&amp;rsquo;s Presenter is first initialised).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We then render the View for the component and pass through the variables that were set-up from within the Presenter.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now I can also open up my &lt;code&gt;:home&lt;/code&gt; View file and add in the &lt;code&gt;a&lt;/code&gt; component there as well just as easily. It would be even easier if I didn&amp;rsquo;t have to manually add the &lt;code&gt;a&lt;/code&gt; component to the &lt;code&gt;:home&lt;/code&gt; View file but that&amp;rsquo;s where running from configuration files like we do at BBC News would come in handy (but that would have been too complicated an implementation for the sake of such a basic example as required for this post).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;presenter&#34;&gt;Presenter&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now let&amp;rsquo;s take a look at one of our Presenters, in this case the Presenter for our &lt;code&gt;b&lt;/code&gt; component…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;require &#39;app/presenters/base&#39;&#xA;require &#39;app/models/b&#39;&#xA;&#xA;class Presenters::B &amp;lt; Presenters::Base&#xA;  attr_reader :run, :name, :age&#xA;&#xA;  def initialize&#xA;    @run = true&#xA;&#xA;    model = B.new(&#39;Mark&#39;, &#39;99&#39;)&#xA;    prepare_view_data({ :name =&amp;gt; model.name, :age =&amp;gt; model.age })&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…as you can see we load a specific Model for this component and then generate our View data by passing the Model information through to a &lt;code&gt;prepare_view_data&lt;/code&gt; method (see below for the implementation details).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;Base&lt;/code&gt; Presenter which our component Presenters inherit from is very straight forward as you can see from the following example…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;module Presenters&#xA;  class Base&#xA;    attr_accessor :model&#xA;&#xA;    def prepare_view_data hash&#xA;      hash.each do |name, value|&#xA;        instance_variable_set(&amp;quot;@#{name}&amp;quot;, value)&#xA;      end&#xA;    end&#xA;  end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…it&amp;rsquo;s just a module namespace with a base class that has a single method &lt;code&gt;prepare_view_data&lt;/code&gt; which dynamically generates instance variables based on the data we passed through from the inheriting Presenter class and which then are usable within the View.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s all there is to it as far as understanding the Presenter pattern. It&amp;rsquo;s a nice clean solution for componentising your different page features and keeping your code more easily maintainable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve created a repo on GitHub called &lt;a href=&#34;https://github.com/Integralist/MVCP&#34; target=&#34;_blank&#34;&gt;MVCP&lt;/a&gt; which is written in &lt;a href=&#34;https://www.ruby-lang.org/&#34; target=&#34;_blank&#34;&gt;Ruby&lt;/a&gt; and uses the &lt;a href=&#34;http://www.sinatrarb.com/&#34; target=&#34;_blank&#34;&gt;Sinatra&lt;/a&gt; web framework. Note: I had some help from my colleague &lt;a href=&#34;http://twitter.com/sthulb&#34; target=&#34;_blank&#34;&gt;Simon&lt;/a&gt; in cleaning up and refactoring some of the code (it may only have been minor changes but as with all good refactorings it made a massive difference to the quality of the code, so thanks to him for helping out).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have any questions then feel free to contact me either here on &lt;a href=&#34;http://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;twitter&lt;/a&gt; and let me know your thoughts.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/design-mvcp/</guid>
      <link>https://www.integralist.co.uk/posts/design-mvcp/</link>
      <pubDate>Tue, 22 Oct 2013 00:00:00 +0000</pubDate>
      <title>MVCP: Model, View, Controller, Presenter</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The unix command line has a hundred or so commands, and a small majority of those you can realistically find yourself using on a regular basis. In this post I want to cover some common commands that can actually be quite useful to you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Shell commands aren&amp;rsquo;t something you can cover in one post. Entire books have been written on the subject. So don&amp;rsquo;t expect anything other than the bare bone basics here, which should hopefully give you enough of an understanding to take your own learning forward.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So let&amp;rsquo;s begin…&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;basics&#34;&gt;Basics&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, so I&amp;rsquo;ll assume you have absolutely no prior command line experience which means we need to start at the basics.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, first things first: open up your shell (if you&amp;rsquo;re on a Mac then this will be your &lt;code&gt;Terminal.app&lt;/code&gt; application.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;what-directory-am-i-currently-in&#34;&gt;What directory am I currently in?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;pwd&lt;/code&gt; - this stands for &amp;ldquo;Print Working Directory&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;how-can-i-see-what-s-in-this-directory&#34;&gt;How can I see what&amp;rsquo;s in this directory?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;ls&lt;/code&gt; - this tells the shell to list out any files or folders in the current working directory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also tell the command a directory path you want it to look inside of: &lt;code&gt;ls ~/Desktop&lt;/code&gt; (this will list all files and folders on your desktop).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;ls -l&lt;/code&gt; - the &lt;code&gt;-l&lt;/code&gt; flag tells the command to stack the list when it prints its output to the shell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;ls -la&lt;/code&gt; - this is a combination of the previous flag and the &lt;code&gt;-a&lt;/code&gt; flag which means &amp;ldquo;show all files&amp;rdquo; (by this I mean, it&amp;rsquo;ll show you hidden files).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;moving-around&#34;&gt;Moving around&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To move around your file system you use the &amp;lsquo;change directory&amp;rsquo; command &lt;code&gt;cd&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;cd ~/Desktop&lt;/code&gt; will put you in the Desktop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also use relative paths such as &lt;code&gt;cd ../&lt;/code&gt; which will take you up one level from wherever you happen to be.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;displaying-content-of-a-file&#34;&gt;Displaying content of a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;cat&lt;/code&gt; command is a concatenation command, meaning that if you ran &lt;code&gt;cat original.txt new.txt&lt;/code&gt; it would display on your screen the combination of the content from both files specified.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, with that understanding we can use &lt;code&gt;cat original.txt&lt;/code&gt; (i.e. specifying just a single file) to show the contents of that file.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;copy-a-file&#34;&gt;Copy a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To copy a file we need the &lt;code&gt;cp&lt;/code&gt; command, and we tell it what file to copy and where to copy it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;cp ~/Downloads/test.txt ~/Desktop/test.txt&lt;/code&gt; will copy the file &lt;code&gt;test.txt&lt;/code&gt; (which is inside our &amp;lsquo;Downloads&amp;rsquo; folder) and put the copy on our Desktop.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;move-a-file&#34;&gt;Move a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To move a file you need the &lt;code&gt;mv&lt;/code&gt; command, and we tell it what file to move and where to move it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;mv ~/Downloads/test.txt ~/Desktop/test.txt&lt;/code&gt; will move the file &lt;code&gt;test.txt&lt;/code&gt; from our &amp;lsquo;Downloads&amp;rsquo; folder onto our &amp;lsquo;Desktop&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;create-a-file&#34;&gt;Create a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To create a file you need the &lt;code&gt;touch&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;touch ~/some-test-file.txt&lt;/code&gt; will create an empty text file in your home directory&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;rename-a-file&#34;&gt;Rename a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is no &lt;code&gt;rename&lt;/code&gt; command on Unix (although there is in Linux) and so we need to use a trick, the trick being to use the &lt;code&gt;mv&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;mv ~/Downloads/test.txt ~/Downloads/new.txt&lt;/code&gt; will actually rename the file &lt;code&gt;test.txt&lt;/code&gt; to &lt;code&gt;new.txt&lt;/code&gt; as we&amp;rsquo;ve moved the file into the same directory it was already in but with a different name (effectively acting like we renamed it)&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;delete-a-file&#34;&gt;Delete a file&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To delete a file we need the &amp;lsquo;remove&amp;rsquo; command &lt;code&gt;rm&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;rm ~/Downloads/test.txt&lt;/code&gt; will delete our &lt;code&gt;test.txt&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;delete-a-directory&#34;&gt;Delete a directory&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To delete a folder we need the &amp;lsquo;remove&amp;rsquo; command &lt;code&gt;rm&lt;/code&gt; again but this time we need to pass in a couple of flags to the command.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first flag is &lt;code&gt;-f&lt;/code&gt; which means &amp;lsquo;force&amp;rsquo; the removal (otherwise if you try to remove a folder then the shell will try and prevent this as it&amp;rsquo;ll assume you&amp;rsquo;ve made a mistake, and deleting a whole folder could be a big mistake if you&amp;rsquo;re not careful).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The second flag is &lt;code&gt;-r&lt;/code&gt; which means &amp;lsquo;recursively&amp;rsquo;. So you&amp;rsquo;ll recursively delete files within the folder.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;rm -rf ~/Desktop/some-folder&lt;/code&gt; will delete our &lt;code&gt;some-folder&lt;/code&gt; folder on the Desktop.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;create-a-directory&#34;&gt;Create a directory&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To create a directory you can use the make directory command &lt;code&gt;mkdir my_folder_name&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To make creating lots of sub directories easier you can pass a &lt;code&gt;-p&lt;/code&gt; flag like so &lt;code&gt;mkdir -p Assets/{Scripts,Styles}&lt;/code&gt; (notice we use interpolation &lt;code&gt;{}&lt;/code&gt; which lets use specify multiple folder names in the current directory level).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;find-searching-for-files&#34;&gt;Find (searching for files)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;find&lt;/code&gt; command is useful for walking a directory hierarchy and returning a list of files found based on a set of criteria you have determined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The most common pattern is to search for a particular file (or file type) within a project folder. Imagine you want to find a file called &lt;code&gt;package.json&lt;/code&gt; within your project directory which is inside your home directory. Here is how we&amp;rsquo;d use the &lt;code&gt;find&lt;/code&gt; command to do that:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# first we&#39;ll set-up the project directory and some files...&#xA;&#xA;cd ~/ # move in to the user&#39;s home directory&#xA;mkdir project-foobar # make our project directory&#xA;cd project-foobar # move inside the project directory&#xA;touch test.txt {package,blah}.json # this creates 3 files inside our project directory&#xA;ls # =&amp;gt; blah.json   package.json    test.txt&#xA;cd ../ # move back into the user&#39;s home directory and we&#39;ll start searching&#xA;&#xA;# here is the actual &#39;find&#39; command&#xA;find ./project-foobar -name &#39;package.json&#39; # =&amp;gt; ./project-foobar/package.json&#xA;&#xA;find ./project-foobar -name &#39;*.json&#39;&#xA;# =&amp;gt; ./project-foobar/blah.json&#xA;# =&amp;gt; ./project-foobar/package.json&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see from the above example the &lt;code&gt;find&lt;/code&gt; command has three parameters:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the directory to search&lt;/li&gt;&#xA;&lt;li&gt;an optional flag to indicate what we want to search for&lt;/li&gt;&#xA;&lt;li&gt;the file we&amp;rsquo;re searching for&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see this broken down:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;./project-foobar&lt;/code&gt; the directory to search&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-name&lt;/code&gt; the flag/option we&amp;rsquo;ve set is &amp;ldquo;check the name of each item found&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&#39;*.json&#39;&lt;/code&gt; we&amp;rsquo;ve used a wildcard (asterisk &lt;code&gt;*&lt;/code&gt;) to indicate we&amp;rsquo;re interested in &amp;ldquo;any&amp;rdquo; json file&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;recursive-searching&#34;&gt;Recursive searching&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To recursively search for content you need to quote the glob you use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;find . -name &#39;*.go&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;process-results&#34;&gt;Process results&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you want to process the results you get, without a pipe, then use &lt;code&gt;-exec &amp;lt;utility&amp;gt; \;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;find . -name &#39;*.go&#39; -exec grep &#39;my_pattern_im_searching_for&#39; {} \;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;where &lt;code&gt;{}&lt;/code&gt; is a placeholder for the file path&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You&amp;rsquo;ll see the &lt;code&gt;\;&lt;/code&gt; at the end indicates the end of the command. You need to escape the &lt;code&gt;;&lt;/code&gt; otherwise it won&amp;rsquo;t work. Also you can replace it with &lt;code&gt;\+&lt;/code&gt; which &lt;em&gt;appends&lt;/em&gt; file paths. The reason you&amp;rsquo;d use this is if you want to execute your specified utility command once and have all matching file paths added as arguments. Whereas &lt;code&gt;\;&lt;/code&gt; means it&amp;rsquo;ll execute the command once for each file matched.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;finding-files-over-a-certain-size&#34;&gt;Finding files over a certain size&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# all files greater than 1mb&#xA;find $HOME/. -size +1024k &#xA;&#xA;# all files inside current directory greater than 500k&#xA;find . -name &#39;*.js&#39; -size +500k &#xA;&#xA;# find all files larger than zero but less than 500bytes&#xA;find . -size +0 -a -size -500c # (-a is AND, -c is bytes) &#xA;&#xA;# find all all files larger than zero OR (-o) any that haven&#39;t been accessed in over a year&#xA;find . -size 0 -o -atime +365&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;grep-searching-for-patterns&#34;&gt;Grep (Searching for patterns)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Grep is a command that lets you find a pattern (either a string or a regular expression) inside of a file or list of files.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;grep &#39;something&#39; test.txt&lt;/code&gt; looks for the word &amp;lsquo;something&amp;rsquo; inside of the file &lt;code&gt;test.txt&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To use grep on a directory of files then we need to use an additional flag: &lt;code&gt;-r&lt;/code&gt; which means &amp;lsquo;recursive&amp;rsquo; (similar to the &lt;code&gt;rm&lt;/code&gt; command we saw previously).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;grep -r &#39;something&#39; ~/Desktop&lt;/code&gt; looks for the word &amp;lsquo;something&amp;rsquo; inside of any files on the Desktop.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;sed-find-and-replace&#34;&gt;Sed (Find and Replace)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;sed&lt;/code&gt; command stands for (S)tream (Ed)itor and allows you to  read in the contents of a file and then write the modified output to another file or pipe it through to another I/O command (we&amp;rsquo;ll cover piping later).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A basic example of its use would be: &lt;code&gt;sed s/day/night/ novel.txt&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This replaces the first occurrence of &amp;lsquo;day&amp;rsquo; to &amp;lsquo;night&amp;rsquo;. If we wanted to replace multiple occurrences then you would need to pass a &lt;code&gt;g&lt;/code&gt; flag (meaning global) to the regular expression like so: &lt;code&gt;sed s/day/night/g novel.txt&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sed is very powerful and there are many features of the syntax that I don&amp;rsquo;t use. One that&amp;rsquo;s interesting is that you can use regular expressions to match a pattern and then do stuff with the matches, such as deleting the line or duplicating it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Consider the following example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;hi there\nmark\nit&#39;s nice to\nmeet you&amp;quot; &amp;gt; test.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we now run the following sed command we should see the line that has the word &lt;code&gt;mark&lt;/code&gt; is deleted:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cat test.txt | sed &#39;/mark/d&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we run the following sed command we should see any lines that start with &lt;code&gt;i&lt;/code&gt; are duplicated (remove the carrot symbol &lt;code&gt;^&lt;/code&gt; to see any lines that have the character &lt;code&gt;i&lt;/code&gt; duplicated; regardless of whether they&amp;rsquo;re at the start of the line or not):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;cat test.txt | sed &#39;/^i/p&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also &amp;lsquo;edit in place&amp;rsquo; if you&amp;rsquo;re feeling brave:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;find . -name &#39;*.go&#39; -exec sed -i &#39;&#39; &#39;s/&amp;lt;patten&amp;gt;/&amp;lt;replacement&amp;gt;/&#39; {} \;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;awk-looping-logic&#34;&gt;Awk (Looping Logic)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;awk&lt;/code&gt; command reads in each line of a file and splits the line into fields (using whitespace - space, tab - as its default delimiter).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can then execute commands for each line and reference each field.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A basic example of its use would be: &lt;code&gt;awk &#39;{ print $1 }&#39;&lt;/code&gt; which means &amp;ldquo;print the first field found in the current line&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So imagine you have the following &lt;code&gt;test.txt&lt;/code&gt; file…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;This is my first line&#xA;This is my second line&#xA;This is my third line&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…you could print the line number followed by a specific word (in this case the second from last word on each line) using the following awk command: &lt;code&gt;awk &#39;{ print &amp;quot;Line &amp;quot; NR &amp;quot;: &amp;quot; $(NF-1) }&#39; test.txt&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Which would display the following content on your screen…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Line 1: first&#xA;Line 2: second&#xA;Line 3: third&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s break this command down a little…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Awk commands are placed inside of single quotes &lt;code&gt;awk &#39;commands go here&#39;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Inside the single quotes we need a set of brackets to place our specific code we want to run: &lt;code&gt;awk &#39;{ code to run here }&#39;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;We specifically tell awk to &lt;code&gt;print&lt;/code&gt; something to stdout (i.e. the terminal screen).&lt;/li&gt;&#xA;&lt;li&gt;In this case we tell it to print the text &amp;ldquo;Line &amp;rdquo; followed by the current line number &lt;code&gt;NR&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;As part of the same print command we then tell it to print &amp;ldquo;: &amp;rdquo; followed by the second from last number.&lt;/li&gt;&#xA;&lt;li&gt;To do that we use two pieces of syntax &lt;code&gt;$()&lt;/code&gt; and &lt;code&gt;NF&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;NF&lt;/code&gt; stands for (N)umber of (F)ields.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;code&gt;$()&lt;/code&gt; wrapping around &lt;code&gt;NF&lt;/code&gt; is our &amp;lsquo;process substitution&amp;rsquo;. This means we&amp;rsquo;re not just outputting some data but manipulating it by using logic to give us 1 field back from the last, hence it needs to be wrapped in &lt;code&gt;$()&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;piping-i-o&#34;&gt;Piping I/O&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The previous commands &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; are all really useful, but it&amp;rsquo;s when you can combine them that their true power shines.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;input-and-output&#34;&gt;Input and Output&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Unix is based on the principle of &amp;ldquo;input&amp;rdquo; and &amp;ldquo;output&amp;rdquo; (known as &amp;ldquo;I/O&amp;rdquo;). In the Shell you have &lt;code&gt;stdin&lt;/code&gt; (standard input) and &lt;code&gt;stdout&lt;/code&gt; (standard output).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By default, &lt;code&gt;stdin&lt;/code&gt; is your keyboard (i.e. whatever you type into the terminal shell) and &lt;code&gt;stdout&lt;/code&gt; is the terminal (i.e. your screen).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;redirection&#34;&gt;Redirection&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Once you understand &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; you can start to look at redirecting them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example when using the &lt;code&gt;sed&lt;/code&gt; command you could use redirection to not overwrite your original file and instead direct the output &lt;code&gt;stdout&lt;/code&gt; coming from the &lt;code&gt;sed&lt;/code&gt; command to another file: &lt;code&gt;sed s/day/night/g original.txt &amp;gt; new.txt&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;piping&#34;&gt;Piping&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Another way to &lt;em&gt;direct&lt;/em&gt; input and output is to use pipes &lt;code&gt;|&lt;/code&gt; (a vertical bar).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A really simple example would be: look at the &lt;code&gt;sed&lt;/code&gt; command we used earlier (&lt;code&gt;sed s/day/night/ novel.txt&lt;/code&gt;). Rather than actually execute it and have it make the specified change to our file &lt;code&gt;novel.txt&lt;/code&gt; we could instead test the command to make sure it does what we expect it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do that we would use the &lt;code&gt;cat&lt;/code&gt; command (which we looked at previously) and pipe its output through to the &lt;code&gt;sed&lt;/code&gt; command like so…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;cat original.txt | sed s/day/night/g&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, to clarify how this works: we&amp;rsquo;re redirecting the &lt;code&gt;cat&lt;/code&gt; command&amp;rsquo;s &lt;code&gt;stdout&lt;/code&gt; through to the &lt;code&gt;sed&lt;/code&gt; command&amp;rsquo;s &lt;code&gt;stdin&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In our original &lt;code&gt;sed&lt;/code&gt; example we directed the &lt;code&gt;sed&lt;/code&gt; command&amp;rsquo;s &lt;code&gt;stdout&lt;/code&gt; to an actual file (&lt;code&gt;novel.txt&lt;/code&gt;), but in this case it has no &lt;code&gt;stdout&lt;/code&gt; specified so it falls back to the default &lt;code&gt;stdout&lt;/code&gt; which in this case is the terminal shell itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hence the results of the &lt;code&gt;sed&lt;/code&gt; command (the modified content) are displayed on your screen.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;piping-to-vim&#34;&gt;Piping to Vim&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One thing I discovered recently (via &lt;a href=&#34;http://twitter.com/Pand0ra83&#34; target=&#34;_blank&#34;&gt;Crystal Hirschorn&lt;/a&gt;) was that you can&amp;rsquo;t just pipe &lt;code&gt;stdout&lt;/code&gt; into Vim unless you add a hyphen/dash &lt;code&gt;-&lt;/code&gt; to the end of the command like so: &lt;code&gt;ls | vim -&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Otherwise Vim will complain that: &lt;code&gt;Input is not from a terminal&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&amp;rsquo;s a good one to remember!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also you can pipe the input into Vim in read-only mode using the &lt;code&gt;-R&lt;/code&gt; flag as well: &lt;code&gt;ls | vim -R -&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;piping-examples&#34;&gt;Piping examples&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here are three real world examples I&amp;rsquo;ve used recently…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;phantomjs 2&amp;gt;&amp;amp;1 network-test.js | tee log.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this example I&amp;rsquo;m executing a &lt;a href=&#34;http://phantomjs.org/&#34; target=&#34;_blank&#34;&gt;PhantomJS&lt;/a&gt; script &lt;code&gt;network-test.js&lt;/code&gt; but I wanted to capture both the results of the script (which just logs out DNS information into the terminal) and any errors that may have occurred into a log text file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way it works might be a little confusing as it shows some things you might not have seen before: &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt; and &lt;code&gt;tee&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Those two commands may look confusing but it just comes down to understanding the numbers that are associated with specific processes, so…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;0&lt;/code&gt; = &lt;code&gt;stdin&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;1&lt;/code&gt; = &lt;code&gt;stdout&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;2&lt;/code&gt; = &lt;code&gt;stderr&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;…this means &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt; is saying direct &lt;code&gt;2&lt;/code&gt; (any errors) through to &lt;code&gt;1&lt;/code&gt; (standard output).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We then pipe the &lt;code&gt;stdout&lt;/code&gt; through to the &lt;code&gt;tee&lt;/code&gt; command which copies it into a file called &lt;code&gt;log.txt&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;ls File-* | sed &#39;s/\(File-[^-]*\)-\(.*\)/mv &amp;amp; \1\2/&#39; | sh&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this example I&amp;rsquo;m trying to remove a hyphen &lt;code&gt;-&lt;/code&gt; from some file names.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The files I have look like &lt;code&gt;File-A-B.gif&lt;/code&gt; and I want them to be renamed to &lt;code&gt;File-AB.gif&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So first I list out any files in the current directory that begin &lt;code&gt;File-&lt;/code&gt; and then pipe those results through to &lt;code&gt;sed&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sed then uses Regular Expressions to store a reference to the opening part of the file name (in this case &lt;code&gt;File-A&lt;/code&gt;) and then stores the end part of the file name (in this case &lt;code&gt;B.gif&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the second part of the &lt;code&gt;sed&lt;/code&gt; command, instead of doing a &amp;lsquo;replace&amp;rsquo; of what we&amp;rsquo;ve found, we actually pass in a &lt;code&gt;mv&lt;/code&gt; command (remember from before that we can rename a file by using &lt;code&gt;mv original.txt new.txt&lt;/code&gt;). In this case the stored references to the beginning and ending parts of the file&amp;rsquo;s name can be referenced within the replacement section using &lt;code&gt;\1&lt;/code&gt; and &lt;code&gt;\2&lt;/code&gt; (and the &lt;code&gt;&amp;amp;&lt;/code&gt; in regular expressions means, the original string being inspected).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So when we use &lt;code&gt;mv &amp;amp; \1\2&lt;/code&gt; we&amp;rsquo;re saying &amp;ldquo;move the original file and move it to the same directory but using the new name of File-AB.gif (remember &lt;code&gt;\1&lt;/code&gt; is &amp;ldquo;File-A&amp;rdquo; and &lt;code&gt;\2&lt;/code&gt; is &amp;ldquo;B.gif&amp;rdquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally, because the &lt;code&gt;sed&lt;/code&gt; command&amp;rsquo;s replacement is an actual command rather than just a string replacement we pipe that replacement content (which is now &lt;code&gt;sed&lt;/code&gt;&amp;rsquo;s &lt;code&gt;stdout&lt;/code&gt;) over to the &lt;code&gt;sh&lt;/code&gt; bin command to execute and hence actually rename the file(s).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note: whenever you write a shell script, you would store it (for example) inside a file with the extension of &lt;code&gt;sh&lt;/code&gt; and then you&amp;rsquo;d use the terminal command &lt;code&gt;sh&lt;/code&gt; to execute that shell script.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;tmux ls | cut -d : -f 1 | xargs -I {} tmux kill-session -t {}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So in this example I wanted an easy way to destroy all my tmux sessions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically I would run &lt;code&gt;tmux ls&lt;/code&gt; to see what sessions I had (it returns something like &lt;code&gt;0: 1 windows (created Fri Oct  4 18:24:38 2013) [129x33]&lt;/code&gt;, where the opening &lt;code&gt;0&lt;/code&gt; is the number/name of the session followed by details about the session -&amp;gt; in this case &lt;code&gt;1 window&lt;/code&gt;, and when it was created, and the size of that window).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once I had my session number (in this case &lt;code&gt;0&lt;/code&gt;) I could run the command &lt;code&gt;tmux kill-session -t 0&lt;/code&gt; but if I had loads of sessions open I would have to run the same command for all of them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To fix this I tried using the commands Awk and Sed but discovered an issue with &amp;lsquo;scope&amp;rsquo; (which I&amp;rsquo;m still not 100% sure I understand, but I&amp;rsquo;ll explain what happened any way)…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was using &lt;code&gt;tmux ls | awk &#39;{print $1}&#39; | sed &#39;s/://g&#39; | xargs -I {} tmux kill-session -t {}&lt;/code&gt;. This works, but not when you stick it inside an alias for easy reuse.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way it works is that it lists out all the tmux sessions and pipes it over to Awk.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Awk then grabs the first field &lt;code&gt;0:&lt;/code&gt; (remember Awk splits the input line into &amp;lsquo;fields&amp;rsquo; using a space delimiter). We then pipe that over to Sed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sed then uses a regular expression to remove the &lt;code&gt;:&lt;/code&gt; from the &lt;code&gt;0:&lt;/code&gt; leaving us with just &lt;code&gt;0&lt;/code&gt;. We then pipe that through to xargs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;xargs runs our kill-session command and passes through the value of &lt;code&gt;0&lt;/code&gt; into that command using the placeholder &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We define what the placeholder will be using &lt;code&gt;-I&lt;/code&gt; so we could of used &lt;code&gt;-I target&lt;/code&gt; instead if we wanted to like so: &lt;code&gt;tmux ls | awk &#39;{print $1}&#39; | sed &#39;s/://g&#39; | xargs -I target tmux kill-session -t target&lt;/code&gt; and it would of achieved the same.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like I say, this works. But I wanted it inside an alias so I could easily reuse it (I mean, just &lt;em&gt;try&lt;/em&gt; and memorise that massive chunk of commands!?). The moment it went into an alias the xargs failed to work because instead of getting &lt;code&gt;0&lt;/code&gt; it got the entire line &lt;code&gt;0: 1 windows (created Fri Oct  4 18:24:38 2013) [129x33]&lt;/code&gt;. The scope of the argument was being lost some how? A bit annoying really.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My colleague at BBC News (&lt;a href=&#34;http://twitter.com/sthulb&#34; target=&#34;_blank&#34;&gt;Simon Thulbourn&lt;/a&gt; - all round command line wizard, amongst many other technical talents) helped me understand a more efficient and fully functioning version (i.e. it can be safely aliased): &lt;code&gt;tmux ls | cut -d : -f 1 | xargs -I {} tmux kill-session -t {}&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So the only difference here is instead of using both Awk and Sed, we&amp;rsquo;re just using Cut. I&amp;rsquo;ve not mentioned it before but &lt;code&gt;cut&lt;/code&gt; works like this:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Cut splits the input into fields (like Awk does). We then tell it that we want the fields to be split by &lt;code&gt;:&lt;/code&gt; (that&amp;rsquo;s the &lt;code&gt;-d :&lt;/code&gt; section). Then finally we use &lt;code&gt;-f 1&lt;/code&gt; to say we want the first field, which we pipe over to xargs. Otherwise the rest of the command is the same as before.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Nice huh!&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;sequences-and-parallelism&#34;&gt;Sequences and Parallelism&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The use of &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; between commands means the commands are run in a sequence. So for example, if you run &lt;code&gt;x &amp;amp;&amp;amp; y&lt;/code&gt; the &lt;code&gt;y&lt;/code&gt; command will not be run until &lt;code&gt;x&lt;/code&gt; has finished (this is similar to using the semicolon to make commands run sequentially &lt;code&gt;x; y&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The use of a single &lt;code&gt;&amp;amp;&lt;/code&gt; between commands means the commands are run in parallel (meaning they don&amp;rsquo;t wait for each other). So for example, &lt;code&gt;x &amp;amp; y&lt;/code&gt; will mean &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; both run &lt;em&gt;at the same time&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;processes&#34;&gt;Processes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each command you execute is a &amp;ldquo;process&amp;rdquo;. So when we execute the command &lt;code&gt;vim&lt;/code&gt; (which opens up the Vim text editor) we have effectively started up a new &amp;ldquo;process&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;viewing-processes&#34;&gt;Viewing processes&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To view a list of all processes currently running across the system use the &lt;code&gt;ps&lt;/code&gt; command (you can also use &lt;code&gt;ps aux&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re only interested in processes within your current terminal tab then use the &lt;code&gt;jobs&lt;/code&gt; command.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;moving-processes-between-the-fore-background&#34;&gt;Moving processes between the fore/background&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To background a process (e.g. while we have Vim open, if we wanted to move back to the terminal) then we could execute the command &lt;code&gt;&amp;lt;C-z&amp;gt;&lt;/code&gt; (which means pressing the &lt;code&gt;&amp;lt;Ctrl&amp;gt;&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; keys at the same time).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To then bring the latest process (i.e. the last process that was put into the background) to the foreground again you would run the command &lt;code&gt;fg&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have multiple processes in the background then you can look up the processes using &lt;code&gt;job&lt;/code&gt; and then pick one and foreground it using the command &lt;code&gt;fg %n&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the number of the job.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;miscellaneous-commands&#34;&gt;Miscellaneous Commands&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;tee&#34;&gt;&lt;code&gt;tee&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;tee&lt;/code&gt; command you&amp;rsquo;ve seen already now (in our above example) but just to reiterate its use, here is how the manual describes it…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The tee utility copies standard input to standard output, making a copy in zero or more files.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;dig&#34;&gt;&lt;code&gt;dig&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;dig&lt;/code&gt; command is used for carrying out DNS lookups: &lt;code&gt;dig integralist.co.uk&lt;/code&gt; returns the DNS records found for my domain name.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;ps&#34;&gt;&lt;code&gt;ps&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;ps&lt;/code&gt; command stands for (p)rocess (s)tatus&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It shows you all running processes on your computer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can use piping again to narrow down the results to something in particular you know is causing your computer to slow down and then execute another command to kill that process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So: &lt;code&gt;ps aux | grep ruby&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the above example we also pass &lt;code&gt;aux&lt;/code&gt; which basically specifies table of results that should be returned (see: &lt;a href=&#34;http://en.wikipedia.org/wiki/Ps_(Unix)&#34; target=&#34;_blank&#34;&gt;http://en.wikipedia.org/wiki/Ps_(Unix)&lt;/a&gt; for more information).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We then pipe that through to &lt;code&gt;grep&lt;/code&gt; and tell it we&amp;rsquo;re interested only in processes that have the text &lt;code&gt;ruby&lt;/code&gt; somewhere (that way we can narrow down the results printed to the screen).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Finally to kill a particular process you&amp;rsquo;ll need its PID number (which &lt;code&gt;ps aux&lt;/code&gt; would have displayed) so locate that PID and then run &lt;code&gt;kill -9 xxxx&lt;/code&gt; where &lt;code&gt;xxxx&lt;/code&gt; is the PID number you want to stop.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;xargs&#34;&gt;&lt;code&gt;xargs&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I know we&amp;rsquo;ve covered Xargs already in my previous examples, but it&amp;rsquo;s worth mentioning that you can also use the &lt;code&gt;-0&lt;/code&gt; flag which helps with some commands that won&amp;rsquo;t work when passed arguments that have spaces in them (imagine a file name with spaces). Using the &lt;code&gt;-0&lt;/code&gt; flag resolves that issue.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, if the command you want to run only excepts a single argument (for example &lt;code&gt;echo 123&lt;/code&gt;) then you can omit the &lt;code&gt;-I {}&lt;/code&gt; placeholder definition.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;cut&#34;&gt;&lt;code&gt;cut&lt;/code&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Again, we&amp;rsquo;ve covered Cut above already, but just to note that you can change the field delimiter using &lt;code&gt;-d&lt;/code&gt; (e.g. &lt;code&gt;-d ,&lt;/code&gt; would split the line on commas).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, &lt;code&gt;-f&lt;/code&gt; allows a range, not just a single field index. So if you wanted fields 3 to 4 you could do &lt;code&gt;-f 3,4&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another feature of &lt;code&gt;cut&lt;/code&gt; is the &lt;code&gt;-c&lt;/code&gt; flag which cuts based on &amp;lsquo;character position&amp;rsquo; rather than &amp;lsquo;fields&amp;rsquo; like &lt;code&gt;-f&lt;/code&gt; does.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way you could use the &lt;code&gt;-c&lt;/code&gt; flag is to remove whitespace at the start and end of a line like so…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;echo &amp;quot; xyz &amp;quot; | cut -c 2- | rev | cut -c 2- | rev&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;…notice our text &amp;ldquo;xyz&amp;rdquo; has one character of white space at the start and end. So we specifically tell &lt;code&gt;cut&lt;/code&gt; to start at character 2 &lt;code&gt;x&lt;/code&gt; and cut until the end of the line &lt;code&gt;2-&lt;/code&gt; and then we use the &lt;code&gt;rev&lt;/code&gt; command which reverses the content so it becomes &amp;ldquo; zyx&amp;rdquo; and then we again cut from the 2nd character (this time &lt;code&gt;z&lt;/code&gt;) and cut until the end of the line and finally we reverse the line one more time so we&amp;rsquo;re back to where we were initially but with the white space removed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are probably more elegant ways to achieve this but it gives you an indication of how you might want to use a command in unique ways.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;tr&#34;&gt;tr&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;tr&lt;/code&gt; command stands for &amp;lsquo;translate characters&amp;rsquo; and it allows you to change the characters in a string of text into a different set of characters. For example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;foo\nbar\nbaz&amp;quot; | tr &amp;quot;bf&amp;quot; &amp;quot;\!&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;here we&amp;rsquo;re saying: &amp;ldquo;any occurance of the letters &amp;lsquo;b&amp;rsquo; and &amp;lsquo;f&amp;rsquo; that are found in the string &amp;lsquo;foo\nbar\n\baz&amp;rsquo;&amp;rdquo; should be replaced with a &lt;code&gt;!&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice also the &lt;code&gt;\n&lt;/code&gt; (new line) character within our string, which means that when &lt;code&gt;tr&lt;/code&gt; executes and loops over the string it&amp;rsquo;ll see this single line as three individual lines; &lt;code&gt;foo&lt;/code&gt; on the first line, &lt;code&gt;bar&lt;/code&gt; on the second line and &lt;code&gt;baz&lt;/code&gt; on the third line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The result would be&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;!oo&#xA;!ar&#xA;!az&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can also invert the translation; so we can say &amp;ldquo;any occurance of a letter that ISN&amp;rsquo;T &amp;lsquo;b&amp;rsquo; or &amp;lsquo;f&amp;rsquo; then translate them into an &amp;lsquo;!&amp;rsquo;&amp;rdquo;. For example,&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;foo\nbar\nbaz&amp;quot; | tr -c &amp;quot;bf&amp;quot; &amp;quot;\!&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is done using the &lt;code&gt;-c&lt;/code&gt; flag/option. But now if we look at the result you&amp;rsquo;ll find it hasn&amp;rsquo;t quite done what we&amp;rsquo;d expect&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;f!!!b!!!b!!!%&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see we&amp;rsquo;ve not catered for our &lt;code&gt;\n&lt;/code&gt; new lines that were within our original string. The &lt;code&gt;tr&lt;/code&gt; command has seen the new lines and replaced them with an &lt;code&gt;!&lt;/code&gt; because as far as it&amp;rsquo;s concerned a new line isn&amp;rsquo;t either a &amp;lsquo;b&amp;rsquo; or &amp;lsquo;f&amp;rsquo; character.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So we&amp;rsquo;ll need to tweak our command slightly to accommodate our need to keep the new lines:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;foo\nbar\nbaz&amp;quot; | tr -c &amp;quot;bf\n&amp;quot; &amp;quot;\!&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which result in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;f!!&#xA;b!!&#xA;b!!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The last thing I want to show you is the &amp;lsquo;squeeze&amp;rsquo; command which you use by adding the &lt;code&gt;-s&lt;/code&gt; flag/option. What this does is any consecutive letters (e.g. the &amp;lsquo;o&amp;rsquo; in &amp;ldquo;fooobar&amp;rdquo; is repeated consecutively) will be reduced to a single replacement. For example,&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;echo &amp;quot;fooobar&amp;quot; | tr -s &amp;quot;o&amp;quot; &amp;quot;\!&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Results in:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;f!bar&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Whereas if we didn&amp;rsquo;t use the squeeze command we would&amp;rsquo;ve seen &lt;code&gt;f!!!bar&lt;/code&gt; instead (notice the &amp;lsquo;o&amp;rsquo; was translated multiple times)..&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;du&#34;&gt;du&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;du&lt;/code&gt; command stands for &amp;ldquo;disk usage&amp;rdquo; and it will display the amount of space a directory occupies:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;du -s -k ~/*&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;-s&lt;/code&gt; flag displays an entry for each specified file, while the &lt;code&gt;-k&lt;/code&gt; flag displays block counts in 1024-byte (1-Kbyte) blocks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Meaning running the above command will result in the following output (for me anyway):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;0/Users/markmcdonnell/Applications&#xA;1355232/Users/markmcdonnell/Box Documents (backup)&#xA;6987864/Users/markmcdonnell/Box Sync&#xA;1931180/Users/markmcdonnell/Code&#xA;1488196/Users/markmcdonnell/Desktop&#xA;13070884/Users/markmcdonnell/Documents&#xA;964816/Users/markmcdonnell/Downloads&#xA;3578120/Users/markmcdonnell/Dropbox&#xA;17251988/Users/markmcdonnell/Library&#xA;0/Users/markmcdonnell/Movies&#xA;232/Users/markmcdonnell/Music&#xA;1992/Users/markmcdonnell/Pictures&#xA;0/Users/markmcdonnell/Public&#xA;38075864/Users/markmcdonnell/VirtualBox VMs&#xA;56/Users/markmcdonnell/bin&#xA;588988/Users/markmcdonnell/db&#xA;528/Users/markmcdonnell/lib&#xA;2013/Users/markmcdonnell/man&#xA;818320/Users/markmcdonnell/src&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If we modify the command to pipe over to the &lt;code&gt;sort&lt;/code&gt; command, like so &lt;code&gt;du -s -k ~/* | sort -k1nr | less&lt;/code&gt;, then we can make the feedback a little bit more useful (i.e. the directories are sorted by overall size!):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;du: &#xA;38075864        /Users/markmcdonnell/VirtualBox VMs&#xA;17253304        /Users/markmcdonnell/Library&#xA;13070884        /Users/markmcdonnell/Documents&#xA;6987868 /Users/markmcdonnell/Box Sync&#xA;3578120 /Users/markmcdonnell/Dropbox&#xA;1931180 /Users/markmcdonnell/Code&#xA;1488196 /Users/markmcdonnell/Desktop&#xA;1355232 /Users/markmcdonnell/Box Documents (backup)&#xA;964816  /Users/markmcdonnell/Downloads&#xA;818320  /Users/markmcdonnell/src&#xA;588988  /Users/markmcdonnell/db&#xA;1992    /Users/markmcdonnell/Pictures&#xA;528     /Users/markmcdonnell/lib&#xA;232     /Users/markmcdonnell/Music&#xA;56      /Users/markmcdonnell/bin&#xA;20      /Users/markmcdonnell/man&#xA;0       /Users/markmcdonnell/Applications&#xA;0       /Users/markmcdonnell/Movies&#xA;0       /Users/markmcdonnell/Public&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;double-exclamation&#34;&gt;Double exclamation !!&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes you need to execute a command using &lt;code&gt;sudo&lt;/code&gt; privileges. If you forget to do this, don&amp;rsquo;t write out the command again but with &lt;code&gt;sudo&lt;/code&gt; at the start. Don&amp;rsquo;t even use the up arrow key and then move the cursor to the start of the line to type &lt;code&gt;sudo&lt;/code&gt;. All you need to do is to run &lt;code&gt;sudo !!&lt;/code&gt;. The &lt;code&gt;!!&lt;/code&gt; expands to the last command you executed.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;ctrl-r&#34;&gt;Ctrl-r&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Rather than try to remember an old command you typed a few hours ago, let the terminal remember for you. If you press &lt;code&gt;&amp;lt;C-r&amp;gt;&lt;/code&gt; (which is &lt;code&gt;&amp;lt;Ctrl&amp;gt;&lt;/code&gt; and &lt;code&gt;r&lt;/code&gt; keys at the same time) then start typing what you think the command was, the terminal will start to autocomplete using your command history. You can even press &lt;code&gt;&amp;lt;C-r&amp;gt;&lt;/code&gt; multiple times to start cycling through your command history.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This was a pretty fast paced run through of some different unix commands. As time goes on I&amp;rsquo;ll update this post to include other commands and real work use cases that I think would be interesting and useful to those readers new to the command line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If there were any errors or any thing like that then just let me know by pinging me on &lt;a href=&#34;http://twitter.com/integralist&#34; target=&#34;_blank&#34;&gt;twitter&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/basic-shell-scripting/</guid>
      <link>https://www.integralist.co.uk/posts/basic-shell-scripting/</link>
      <pubDate>Tue, 01 Oct 2013 00:00:00 +0000</pubDate>
      <title>Basic Shell Scripting</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;who-is-robert-c-martin&#34;&gt;Who is Robert C. Martin?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Robert C. Martin is a legend in the development industry. Commonly referred to as simply &amp;ldquo;Uncle Bob&amp;rdquo;. He is a software consultant and has been programming since the mid 60&amp;rsquo;s. Over the years he has written many books (some listed below) as well as shared his great knowledge of system design and coding best practices.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Designing Object-Oriented C++ Applications&lt;/li&gt;&#xA;&lt;li&gt;Patterns Languages of Program Design&lt;/li&gt;&#xA;&lt;li&gt;Extreme Programming in Practice&lt;/li&gt;&#xA;&lt;li&gt;Agile Software Development: Principles, Patterns and Practices&lt;/li&gt;&#xA;&lt;li&gt;UML for Java Programmers&lt;/li&gt;&#xA;&lt;li&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/li&gt;&#xA;&lt;li&gt;The Clean Coder: A Code of Conduct for Professional Programmers&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The last book in that list is the focus of this post.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-s-it-all-about&#34;&gt;What&amp;rsquo;s it all about?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Well, I&amp;rsquo;ve taken the liberty to reference the author directly here as I feel his words convey the book&amp;rsquo;s focus more than I ever could…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I presume you just picked up this book because you are a computer programmer and are intrigued by the notion of professionalism. You should be. Professionalism is something that our profession is in dire need of.&#xA;I&amp;rsquo;m a programmer too. I&amp;rsquo;ve been a programmer for 42 years (longer by the time you read this); and in that time I&amp;rsquo;ve seen it all. I&amp;rsquo;ve been fired. I&amp;rsquo;ve been lauded. I&amp;rsquo;ve been a team leader, a manager, a grunt and even a CEO. I&amp;rsquo;ve worked with brilliant programmers and I&amp;rsquo;ve worked with slugs. I&amp;rsquo;ve worked on high-tech cutting-edge embedded software/hardware systems, and I&amp;rsquo;ve worked on corporate payroll systems. I&amp;rsquo;ve programmed in COLBOL, FORTRAN, BAL, PDP-8, PDP-11, C, C++, Java, Ruby, Smalltalk, and a plethora of other languages and systems. I&amp;rsquo;ve worked with untrustworthy pay check thieves, and I&amp;rsquo;ve worked with consummate professionals. It is that last classification that is the topic of this book.&#xA;In the coming years I would be fired from one job for carelessly missing critical dates, and nearly fired from still another for inadvertently leaking confidential information to a customer. I would take the lead on a doomed project and ride it into the ground without calling for the help I knew I needed. I would aggressively defend my technical decisions even though they flew in the face of the customers’ needs. I would hire one wholly unqualified person, saddling my employer with a huge liability to deal with. And worst of all, I would get two other people fired because of my inability to lead.&#xA;So think of this book as a catalog of my own errors, a blotter of my own crimes, and a set of guidelines for you to avoid walking in my early shoes.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;take-responsibility&#34;&gt;Take responsibility&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional takes responsibility for his code and his decisions. His primary focus should be to &amp;lsquo;do no harm&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Don&amp;rsquo;t harm the code:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a short-list of things a professional will do…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ensure that QA (Quality Assurance) find nothing wrong. If there are bugs then a professional will take note of them, how they occurred and aim to prevent it from happening again. A professional doesn&amp;rsquo;t rely on others to catch bugs for them.&lt;/li&gt;&#xA;&lt;li&gt;Know how all the code works (even the bits they didn&amp;rsquo;t write). Understand all of the codebase and how the different components inter-lock. The only way a professional can apply an appropriate solution is to know the environment, its limitations and constraints.&lt;/li&gt;&#xA;&lt;li&gt;Write tests (unit &amp;amp; acceptance) and will ensure they are automated. A professional who writes tests first before code will be more confident in adding new features and refactoring existing code as they have the tests to back them up as they make changes (especially if the tests are automated then the red/green/refactor cycle can be tightly integrated into the professionals work flow).&lt;/li&gt;&#xA;&lt;li&gt;100% code coverage (or at least in the 90% range). TDD (Test Driven-Development) means that the code design allows every line of code the professional writes to be easily testable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Do not harm the code&amp;rsquo;s architecture/structure:&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A professional will keep in mind the following…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Software should be easy to change.&lt;/li&gt;&#xA;&lt;li&gt;Making a change to the code base should be easy. If it isn&amp;rsquo;t then the professional will look to change the design of the code to accommodate this requirement so the code becomes more flexible and allows changes to be made more easily in future.&lt;/li&gt;&#xA;&lt;li&gt;Any code the professional reads over or makes a change to will be analysed for any potential improvements to the code&amp;rsquo;s structure (this is known as &amp;lsquo;merciless refactoring&amp;rsquo; or &amp;lsquo;the boy scout rule&amp;rsquo;). In other words always commit back a module in a better state than you originally checked it out.&lt;/li&gt;&#xA;&lt;li&gt;Make continuous changes to the code base. Constantly changing the code (i.e. improving it) should result in greater flexibility and modularity. If you leave the code static (e.g. you&amp;rsquo;re afraid to change it in case it breaks something) then when management requests a change or new feature you may likely find the code is too rigid to be adapted.&lt;/li&gt;&#xA;&lt;li&gt;Don&amp;rsquo;t be afraid to constantly change your code. Your tests are there to back you up and should be quick to run!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;work-ethic&#34;&gt;Work ethic&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Your career is &lt;em&gt;your&lt;/em&gt; responsibility, do not leave it up to your employer to train you, send you on courses or buy you books. Take control of yourself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The time you spend at work should be spent on your employers problems, not yours. A professional works hard for his employer and makes time for his &amp;lsquo;career&amp;rsquo; in his own time. This also doesn&amp;rsquo;t mean you should spend all your time on your career. You have a family/life too. Balance your work, your career and your life in appropriate measures.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;know-your-field&#34;&gt;Know your field&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Professionals not only know their chosen favourite technologies, but have an understanding and interest in other technologies outside of that circle.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Professionals will know past techniques (and why they may no longer be relevant) as well as the current best practices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Professionals will also know the pros and cons to specific techniques and when to choose one over the other.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Uncle Bob makes a comment which references the &amp;ldquo;Santayana&amp;rsquo;s curse&amp;rdquo;…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Those who cannot remember the past are condemned to repeat it.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here is a short list of things you should know (or at least be quite familiar with):&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Design patterns (GOF 24 patterns)&lt;/li&gt;&#xA;&lt;li&gt;Design principles (SOLID, DRY, SRP, DIP)&lt;/li&gt;&#xA;&lt;li&gt;Methods of working (Agile, Scrum, Kanban, Waterfall)&lt;/li&gt;&#xA;&lt;li&gt;Disciplines (TDD, BDD, OOP, CI, Pair Programming)&lt;/li&gt;&#xA;&lt;li&gt;Artifacts (UML, sequence diagrams, flow charts, decision tables)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;stay-current&#34;&gt;Stay current&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Practice. Doing your job isn&amp;rsquo;t practice. Your job helps you improve your current skills, practice is learning new related skills.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Professionals will participate in Code Katas. These aren&amp;rsquo;t about solving problems because as a professional they would have already solved the problems presented in the kata. The purpose of code katas for a professional is to help warm them up for the days work and as a warm down at the end of the day. It allows them to try out different options for refactoring the solution and finding other shortcuts.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;collaborate&#34;&gt;Collaborate&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional will plan, design and write code together with their team/co-workers. This helps open their knowledge up to new ways of thinking and solutions they may not have considered otherwise. This also facilitates faster learning and making fewer errors.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;mentoring&#34;&gt;Mentoring&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Nothing demonstrates more how much you know about a subject than when you try to teach it to some one else. Juniors will ask all sorts of questions you may have long forgotten about (such as why you no longer build something in a certain way or using a certain technique). Professionals look after juniors and don&amp;rsquo;t let them struggle on without help and direction.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;know-your-domain&#34;&gt;Know your domain&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional will research the business they are now building software for. So if you work for a travel agent then you should know a bit about that industry. You don&amp;rsquo;t need to be an expert, just know enough to recognise concerns with certain technical requests or specifications.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;identify-with-your-employer&#34;&gt;Identify with your employer&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Effectively your employers problems are your problems and so you need to take their perspective and understand the features they want implemented. A professional will be in a better position to advise whether those new features are actually right for the business.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;learn-to-say-no&#34;&gt;Learn to say no&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If your boss tells you to implement a feature by a certain date and you know that can&amp;rsquo;t happen without compromising the quality and stability of the software, then be vocal and say &amp;ldquo;no, that&amp;rsquo;s not possible&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A professional wouldn&amp;rsquo;t flat out say &amp;ldquo;No&amp;rdquo; and walk away, they would suggest a date that the work could be completed by, or possibly a compromise in the features that would be implemented by the deadline date. A professional will work with management to agree on what&amp;rsquo;s achievable but won&amp;rsquo;t settle for intimidation because management has tried to enforce an unrealistic request.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As a professional you were hired to carry out a specific specialised job and it&amp;rsquo;s your responsibility to educate management on what&amp;rsquo;s feasible or not. Do not find yourself agreeing to impossible deadlines or saying &amp;ldquo;I&amp;rsquo;ll try&amp;rdquo; (I&amp;rsquo;ll try is usually interpreted by management as &amp;ldquo;yes&amp;rdquo;). Generally developers will agree to &amp;ldquo;try&amp;rdquo; because they want to avoid confrontations but it suggests that the work you were doing previously wasn&amp;rsquo;t&amp;rsquo; actually your all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What does &amp;ldquo;I&amp;rsquo;ll try&amp;rdquo; actually mean any way? That you&amp;rsquo;ll work longer hours or work weekends? No, of course not. So why tell management you&amp;rsquo;ll &amp;ldquo;try&amp;rdquo; when you&amp;rsquo;re just going to go ahead and do what you was planning on doing before. It will just let them down when you don&amp;rsquo;t succeed to finish by the deadline because management will have interpreted your &amp;ldquo;I&amp;rsquo;ll try&amp;rdquo; as &amp;ldquo;I will&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;rules-and-principles-for-coding&#34;&gt;Rules and principles for coding&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional has a specific set of principles when it comes to how they work…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Professionals are prepared (always focused and understanding)&lt;/li&gt;&#xA;&lt;li&gt;Professionals don&amp;rsquo;t write code when tired or distracted as this just results in code that doesn&amp;rsquo;t work or will just need to be rewritten later.&lt;/li&gt;&#xA;&lt;li&gt;Professionals avoid &amp;ldquo;the zone&amp;rdquo;. This sounds controversial as &amp;ldquo;the zone&amp;rdquo; is what most developers think gives them their edge. That sweet moment where everything seems to be flowing just right. But &amp;ldquo;the zone&amp;rdquo; just tricks you into thinking the speed you&amp;rsquo;ve gained processing problems means they are really efficient. They aren&amp;rsquo;t. You lose the bigger picture when you get into the &amp;ldquo;flow&amp;rdquo;. So don&amp;rsquo;t buy into it. Be focused.&lt;/li&gt;&#xA;&lt;li&gt;Professionals don&amp;rsquo;t code while listening to music. You aren&amp;rsquo;t as productive as you think you are. This is something I&amp;rsquo;ve personally experienced and agree with. Working in silence may seem boring or too solitary but I do my best work when the background noise disappears.&lt;/li&gt;&#xA;&lt;li&gt;Professionals handle interruptions politely and be willing to help regardless. Have you ever given an agitated response to someone who has interrupted you while working? Your snappy response could be because you&amp;rsquo;re trying to figure out a complicated problem that requires total concentration (maybe you were trying to get &amp;ldquo;into the zone&amp;rdquo;). But a professional knows how to politely handle the situation and return to the problem at hand.&lt;/li&gt;&#xA;&lt;li&gt;Professionals know that &amp;ldquo;writers block&amp;rdquo; can usually be solved (or alleviated) by pair programming.&lt;/li&gt;&#xA;&lt;li&gt;Professionals know to produce creative output they need creative input. It&amp;rsquo;ll be different for each individual but find out what gets your creative juices flowing and make sure you indulge that as often as possible to allow your more creative output to flow.&lt;/li&gt;&#xA;&lt;li&gt;Professionals avoid time fixing bugs. No other profession would stand for bugs in this way too long (could you imagine a doctor who made mistakes in diagnosis on every patient? he wouldn&amp;rsquo;t last in this profession very long!), so a software professional should aim to reduce debugging time to zero.&lt;/li&gt;&#xA;&lt;li&gt;Professionals aren&amp;rsquo;t afraid to go home when there is a bug they can&amp;rsquo;t solve. They recognise their creative periods, and so know when to take a break. You&amp;rsquo;ll find that your subconscious will figure out the solution while your brain takes a rest - so remember that it&amp;rsquo;s ok to walk away and take a break.&lt;/li&gt;&#xA;&lt;li&gt;Professionals know that being late for a deadline is a fact of life and unavoidable. But a professional will constantly measure their progress and inform those who need to know as early as possible if they&amp;rsquo;re not going to make the deadline. Don&amp;rsquo;t let people down at the last minute.&lt;/li&gt;&#xA;&lt;li&gt;Professionals don&amp;rsquo;t give false hope that a deadline will be met if there genuinely is no chance. Better to formulate a fall-back plan or agree what can be achieved. Stick to your estimates, don&amp;rsquo;t let a manager try to convince you to &amp;ldquo;do what it takes&amp;rdquo; to make the deadline.&lt;/li&gt;&#xA;&lt;li&gt;Professionals don&amp;rsquo;t build a wall around their code. Any developer should be allowed/able to make changes to other developers code.&lt;/li&gt;&#xA;&lt;li&gt;Professionals understand that pair programming is a good thing in that it helps you learn the system, find bugs faster and share knowledge more efficiently.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;acceptance-tests&#34;&gt;Acceptance Tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Acceptance tests help avoid ambiguity in feature requests and how the existing system functions. They are different from unit-tests (which test individual components of the code) in that they ensure the finished application functions how the business expects it to (without the business having to understand the technical aspects of the system).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These types of tests should be co-written by a stakeholder &amp;amp; a programmer to ensure clarity and accuracy, and they should always be written so they can be executed automatically.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Acceptance tests provide the entire team with the definition of &amp;ldquo;done&amp;rdquo; (e.g. code written, tests passing, code deployed &amp;amp; QA satisfied).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Professionals should never be passive-aggressive when it comes to acceptance tests. By this we mean: if you&amp;rsquo;ve been asked to implement a test that you think is faulty then it is your responsibility as a professional to make the business understand why the test is faulty and to come to an agreement on what an acceptable test should be. So don&amp;rsquo;t act passive-aggressively (in a &amp;ldquo;well if this is what they wanted, then this is what they&amp;rsquo;ll get&amp;rdquo; way) by allowing a faulty test to pass.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;managing-time&#34;&gt;Managing time&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional knows how to manage their time.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;meetings&#34;&gt;Meetings&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;They don&amp;rsquo;t go to every meeting they are invited to just because they&amp;rsquo;re invited. They only go to those meetings that affect the immediate job they&amp;rsquo;re working on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The people who invite you to meetings aren&amp;rsquo;t responsible for managing your time, you are. Be wise about the time you give up as it otherwise will mean your work won&amp;rsquo;t get done.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A good manager will do what they should to keep you out of meetings.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If a meeting gets boring: leave. It&amp;rsquo;s unprofessional to stay in a meeting where your input is not needed. Be polite and excuse yourself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Only agree to attend meetings where a clear agenda has been determined.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;scrum&#34;&gt;Scrum&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Participates in a Scrum stand-up meeting should spend no more than 20 seconds per question (what did I do yesterday, what am I doing today, what&amp;rsquo;s blocking me)&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;sprint-planning&#34;&gt;Sprint Planning&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sprint Planning sessions are a notoriously difficult part of Agile to get right. But effectively: estimates for backlog items should already be done, ready for selection/rejection. Ideally acceptance tests will also have already been written. No more than 10mins should be spent reviewing any item. If more time is needed then another meeting should be scheduled with a subset of the team to discuss further.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;sprint-retro&#34;&gt;Sprint Retro&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sprint Retro should only take 20mins and your sprint demo should only take 25mins. For most Agile teams it will only have been two weeks since your last retro so there shouldn&amp;rsquo;t be &lt;em&gt;that much&lt;/em&gt; to talk about.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;discussions&#34;&gt;Discussions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Any argument that lasts longer than 5mins can not be settled by arguing. Get data to back up your opinions and to solidify a decision.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;code&#34;&gt;Code&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Avoid blind alleys. A blind alley is where you choose a technical solution and stick with it even though later on you realise it&amp;rsquo;s not the right choice. Learn to stop digging that hole. Back out and try something different.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Avoid messes. A mess is like a time black hole that sucks you in. Every step you think you&amp;rsquo;re closer to the finish, and it seems to be better than starting over. Don&amp;rsquo;t fall for it!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Blind alleys and messes have very subtle differences but basically both should be recognised as early as possible so you can escape them.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;estimations&#34;&gt;Estimations&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional will try not to estimate a job by themselves. Any one who does this should expect to go over by at least 3 times as long as their original estimate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Professionals will estimate with the help of their team as they know someone on the team may highlight an issue the others (including yourself) have missed or not considered.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If appropriate, try breaking up a task into smaller tasks and estimating each smaller task. In doing so you&amp;rsquo;ll likely find that the total sum of your estimate is larger than your original estimate would have been for the whole thing (i.e. before you split the task into smaller chunks).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;pressure&#34;&gt;Pressure&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A professional knows to stay calm under pressure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A clear head is essential. No good comes from pent up frustration at management for tight deadlines, or poor software (when a build breaks just before going live).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A professional resorts to discipline and training to get through these situations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ultimately: by handling your job and your responsibilities &lt;em&gt;professionally&lt;/em&gt; you&amp;rsquo;ll be able to avoid pressure by avoiding situations that cause pressure.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This has been a bit of a whirlwind tour of &amp;ldquo;The Clean Coder: A Code of Conduct for Professional Programmers&amp;rdquo; but hopefully you&amp;rsquo;ve learnt a few things about how to handle yourself in a professional manner and will want to pick up the book to get the full benefit of &amp;ldquo;Uncle Bob&amp;rsquo;s&amp;rdquo; experience and advice.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I cannot recommend this book enough. I can see it being a useful tool for not only developers but for managers as well, because although the book is primarily focused on people in the software engineering industry, the information and tips are still relevant cross-discipline.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/clean-coder/</guid>
      <link>https://www.integralist.co.uk/posts/clean-coder/</link>
      <pubDate>Sat, 01 Jun 2013 00:00:00 +0000</pubDate>
      <title>Clean Coder</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In my &lt;a href=&#34;/posts/design-oop/&#34;&gt;previous post&lt;/a&gt; I quoted the following description of object-oriented design…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Object-Oriented Design is about the messages that get sent between objects and not the objects themselves.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The reason I felt this quote was important for good code design was because it helped focus our attention on improving our object&amp;rsquo;s interfaces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Since then I&amp;rsquo;ve been reading through &lt;a href=&#34;http://designpatternsinruby.com&#34; target=&#34;_blank&#34;&gt;Design Patterns in Ruby&lt;/a&gt; by Russ Olsen, and in the chapter on the Proxy design pattern he reiterates thinking about objects more from the perspective of &amp;lsquo;messages&amp;rsquo; and how that can help improve the Proxy pattern implementation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;His comments really nailed home for me the design benefits of thinking more about &amp;lsquo;messages&amp;rsquo; being passed to objects, and it&amp;rsquo;s that point which I want to elaborate on below.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;quick-example&#34;&gt;Quick example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Imagine the following code example: &lt;code&gt;account.deposit(50)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When thinking about a statically typed language, object methods are generally considered to be more &amp;lsquo;baked&amp;rsquo; into the objects, in the sense that running the above code example suggests you are &amp;lsquo;calling&amp;rsquo; the &lt;code&gt;deposit&lt;/code&gt; method found on the &lt;code&gt;account&lt;/code&gt; object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But in a dynamically typed language (such as Ruby) this doesn&amp;rsquo;t make a lot of sense because the &lt;code&gt;account&lt;/code&gt; object might not actually contain a method called &lt;code&gt;deposit&lt;/code&gt; (statically typed languages are compiled and so we can be assured that if we call a method on an object, it will be there - otherwise the program would fail to compile) so talking about &amp;lsquo;calling&amp;rsquo; a method on an object is not as accurate as describing it like so:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;we&amp;rsquo;re sending a deposit message to an account object&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;the-proxy-design-pattern&#34;&gt;The Proxy Design Pattern&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The Proxy design pattern is where we place an object between the user and the actual object the user wishes to interact with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a few different types of proxy object:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Protection proxies&lt;/li&gt;&#xA;&lt;li&gt;Remote proxies&lt;/li&gt;&#xA;&lt;li&gt;Virtual proxies&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The reason &amp;lsquo;message passing&amp;rsquo; came up in the Proxy design pattern (specifically when developing a &amp;lsquo;virtual proxy&amp;rsquo; - which is where we create a proxy object to prevent an expensive object instantiation operation from happening until the user &amp;lsquo;actually&amp;rsquo; interacts with one of the methods on the real object) was because the author wanted to avoid the situation where we would need to implement a stub method for each method found on the real object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t necessarily an issue for all types of objects. But if you look at built-in objects such as the &lt;code&gt;Array&lt;/code&gt; object, that has approximately 118 (maybe more) methods! So for us to implement a proxy for that object we&amp;rsquo;d theorectically need to implement 118 stub methods, each of which would simply forward on the request to the corresponding method on the real object to handle. That would not only be tedious but an inefficient way to implement our proxy object.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-ruby-handles-method-calls&#34;&gt;How Ruby handles method calls&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In Ruby if you pass a message (e.g. call a method) to an object and that method doesn&amp;rsquo;t exist, then Ruby will try to find another method on that object: &lt;code&gt;method_missing&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If &lt;code&gt;method_missing&lt;/code&gt; doesn&amp;rsquo;t exist then Ruby will try to lookup the method on the parent object, and will keep moving up the inheritance chain until it reaches the core &lt;code&gt;Object&lt;/code&gt; object (which does implement &lt;code&gt;method_missing&lt;/code&gt;) and which simply raises a &lt;code&gt;NoMethodError&lt;/code&gt; exeception.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;implementing-method-missing&#34;&gt;Implementing &lt;code&gt;method_missing&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you implement &lt;code&gt;method_missing&lt;/code&gt; on your proxy object then you can pass on the message to the real object more efficiently than stubbing the method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So instead of this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-ruby&#34;&gt;class AccountProxy&#xA;    def initialize(real_object)&#xA;        @real_object = real_object&#xA;    end&#xA;    &#xA;    def deposit(amount)&#xA;        @real_object.deposit(amount)&#xA;    end&#xA;    &#xA;    … ad infinitum … &#xA;end&#xA;&#xA;account = Account.new&#xA;proxy = AccountProxy.new(account)&#xA;proxy.deposit(50)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…we should really take advantage of the dynamic nature of the Ruby language to avoid having to manually write out these methods by hand, like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-ruby&#34;&gt;class AccountProxy&#xA;    def initialize(real_account)&#xA;        @subject = real_account&#xA;    end&#xA;    def method_missing(name, *args)&#xA;        @subject.send(name, *args)&#xA;    end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can see from the above example that we&amp;rsquo;re using the &lt;a href=&#34;http://ruby-doc.org/core-2.0/Object.html#method-i-send&#34; target=&#34;_blank&#34;&gt;send&lt;/a&gt; method to pass the message (i.e. the method invoked by the user on the proxy object) directly to the real object.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As you can see, focusing on passing messages not only helps inform us of better interfaces when designing our application but also makes us more efficient by utilising features unique to dynamically typed languages.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/message-passing-in-object-oriented-code/</guid>
      <link>https://www.integralist.co.uk/posts/message-passing-in-object-oriented-code/</link>
      <pubDate>Sun, 31 Mar 2013 00:00:00 +0000</pubDate>
      <title>Message Passing in Object Oriented Code</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;quick-summary&#34;&gt;Quick Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here is a short summary for those of you who prefer to see a quick bullet-point list of items covered&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Decouple your code (&lt;em&gt;we discuss this in more detail below&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Describe your class to see if it does too much&lt;br&gt;&#xA;e.g. for each class write down a single line description and try to avoid the words &amp;lsquo;and&amp;rsquo;, &amp;lsquo;or&amp;rsquo; from occuring&lt;/li&gt;&#xA;&lt;li&gt;Review each method thoroughly (you may find some methods don&amp;rsquo;t belong in your class and deserve their own interface)&lt;/li&gt;&#xA;&lt;li&gt;Manage your dependencies:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Check the method arguments you&amp;rsquo;re passing around&lt;/li&gt;&#xA;&lt;li&gt;Use dependency injection (don&amp;rsquo;t hard code class names)&lt;/li&gt;&#xA;&lt;li&gt;Avoid direct references to complex data structures (transform your data into a more appropriate form)&lt;/li&gt;&#xA;&lt;li&gt;Abide by the Single Responsibility Principle (SRP)&lt;/li&gt;&#xA;&lt;li&gt;Review comments to ensure their purpose and usefulness&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Your commented code could be better handled by moving into a separate method with a descriptive name&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Write more flexible interfaces:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Object-Oriented code is more about the &amp;lsquo;messages&amp;rsquo; sent between objects than the objects themselves&lt;/li&gt;&#xA;&lt;li&gt;Think about the messages you want to send and create objects/interfaces to handle them&lt;/li&gt;&#xA;&lt;li&gt;Ask for what you &lt;em&gt;want&lt;/em&gt; and don&amp;rsquo;t include &lt;em&gt;how&lt;/em&gt; to do what you want&lt;/li&gt;&#xA;&lt;li&gt;Ensure messages you send (e.g. method calls you make) don&amp;rsquo;t rely on knowledge of the object that implements the method&lt;/li&gt;&#xA;&lt;li&gt;Reduce your object&amp;rsquo;s context (i.e. how much it knows about other objects). Dependency Injection can help here&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Trust your objects (e.g. Duck Typing design principles)&lt;/li&gt;&#xA;&lt;li&gt;If using the inheritance pattern:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Abstract your shared functionality into the base class&lt;/li&gt;&#xA;&lt;li&gt;Make sure sub classes inherit only what they need&lt;/li&gt;&#xA;&lt;li&gt;Avoid calling &lt;code&gt;super&lt;/code&gt; as it&amp;rsquo;s a code smell&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;All of the following information has been distilled from Sandi Metz&amp;rsquo; &lt;a href=&#34;http://www.poodr.info/&#34; target=&#34;_blank&#34;&gt;Practical Object-Oriented Design in Ruby&lt;/a&gt;, and although the code in this post is based on the Ruby language, don&amp;rsquo;t worry - the concepts are applicable for any object-oriented language.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would highly recommend you read &lt;a href=&#34;http://www.poodr.info/&#34; target=&#34;_blank&#34;&gt;Practical Object-Oriented Design in Ruby&lt;/a&gt; as the author goes into far more code detail and background information (as well as covering other subjects such as test-driven development and the process of writing efficient unit tests) which will help you understand the concepts better than I could in this single post. But hopefully the following distilled version should be a sufficient starting point for your journey into writing more flexible and maintainable code.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;objects&#34;&gt;Objects&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The best description I have ever read regarding good Object-Oriented design goes like this&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Object-Oriented Design is about the messages that get sent between objects and not the objects themselves.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This single line quote perfectly captures the intention behind good Object-Oriented design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It seems our focus on objects has been wrong. We should be thinking primarily about the messages we want to send. This way we build up classes based on good clean interfaces and so our subsequent objects are clearer and more direct in their message handling.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;class-analysis&#34;&gt;Class Analysis&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We want our classes to be as decoupled as possible. The benefit of this is to allow changes to occur over time with little to no side-effects. If your classes have too many dependencies, which are likely too tightly coupled to the class, then any design/code changes in the future could potentially have a negative knock-on effect on the rest of your code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To ensure a class only contains the behaviour it needs try describing your class in one sentence. If you find you have to use the word &amp;ldquo;and&amp;rdquo; within your description then the class appears to have more than one responsibility (this is a bad thing - your classes should be small and focused on a single responsibility). If you find you have used the word &amp;ldquo;or&amp;rdquo; to describe your class then you not only have more than one responsibility but the responsibilities aren&amp;rsquo;t even related. That again would be an indication of a code smell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another way to analyse your classes is to ask each method within the class a question, and to see if any of the answers sound out of place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;e.g. &amp;ldquo;Please Mr. &lt;code&gt;ClassName&lt;/code&gt; what is your &lt;code&gt;method_name&lt;/code&gt;?&amp;rdquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This sounds strange and maybe a bit childish, but it&amp;rsquo;s surprising what methods suddenly appear to no longer fit within the responsibilities of the class being interrogated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, look at the following class which is based on a part of a bicycle (specifically gears)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Gear&#xA;    attr_reader :chainring, :cog, :rim, :tire&#xA;    &#xA;    def initialize (chainring, cog, rim, tire)&#xA;      @chainring = chainring&#xA;      @cog       = cog&#xA;      @rim       = rim&#xA;      @tire      = tire&#xA;    end&#xA;&#xA;    def ratio&#xA;      chainring / cog.to_f&#xA;    end&#xA;&#xA;    def gear_inches&#xA;        # tire goes around rim twice for diameter&#xA;        ratio * (rim + (tire * 2))&#xA;    end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;now start to ask each of its methods a question (remember that &lt;code&gt;attr_reader&lt;/code&gt; generates a getter method and so those need to be queried as well)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&amp;ldquo;Please Mr. &lt;code&gt;Gear&lt;/code&gt; what is your &lt;code&gt;ratio&lt;/code&gt;?&amp;rdquo; &lt;strong&gt;- seems fine&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&amp;ldquo;Please Mr. &lt;code&gt;Gear&lt;/code&gt; what is your &lt;code&gt;gear_inches&lt;/code&gt;?&amp;rdquo; &lt;strong&gt;- seems fine also&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&amp;ldquo;Please Mr. &lt;code&gt;Gear&lt;/code&gt; what is your &lt;code&gt;tire&lt;/code&gt;?&amp;rdquo; &lt;strong&gt;- hmm? notice this doesn&amp;rsquo;t sound like it quite fits the purpose of a &amp;lsquo;Gears&amp;rsquo; class&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;You can tell that the &lt;code&gt;tire&lt;/code&gt; method doesn&amp;rsquo;t fit in with a class which handles bicycle gears information and would be better suited to be placed in its own class. A simple querying of the methods has pointed us in the direction of a potential code smell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One other potential code smell worth avoiding is the direct referencing of class attributes/properties. You should only access them via a getter method to ensure good separation of data access. For example&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Gear&#xA;    attr_reader :chainring, :cog&#xA;    &#xA;    def initialize (chainring, cog)&#xA;      @chainring = chainring&#xA;      @cog       = cog&#xA;    end&#xA;&#xA;    def ratio&#xA;      @chainring / @cog.to_f # bad&#xA;      chainring / cog.to_f   # good&#xA;    end&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;dependencies&#34;&gt;Dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Dependencies can be many things, for example: external class references or arguments passed to methods.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some rules to help you spot a dependency and how to better manage them&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;direct-references&#34;&gt;Direct References&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Avoid &amp;lsquo;direct references&amp;rsquo;. These are things like drilling down into a complex array structure to grab some data to work with. You may know the data structure now, but that&amp;rsquo;s not to say it won&amp;rsquo;t change in the future. But also, linking to a complicated data structure is confusing to other users because it obscures what the data really is and what it is meant to represent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in the following example we are directly accessing &lt;code&gt;item[0]&lt;/code&gt; and &lt;code&gt;item[1]&lt;/code&gt; from a multi-dimensional array&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#BAD&#xA;class MyClass&#xA;    attr_reader :data&#xA;    &#xA;    def initialize(data)&#xA;        @data = data&#xA;    end&#xA;&#xA;    def do_something&#xA;        data.each do |item| &#xA;            puts item[0]&#xA;            puts item[1]&#xA;            puts &#39;---&#39;&#xA;        end&#xA;    end&#xA;end&#xA;&#xA;obj = MyClass.new([[10, 25],[3, 9],[41, 7]])&#xA;obj.do_something&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;but the order of the items may not always be what you think they are and the direct access is not very descriptive of what the data is that you&amp;rsquo;re accessing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead you should &amp;lsquo;transform&amp;rsquo; your data structure into a simpler and easier to understand structure (a good way to do this in Ruby is by using &lt;code&gt;Struct&lt;/code&gt; which is perfect for creating basic data holding classes - which is what we want to do here)&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;#GOOD&#xA;class MyClass&#xA;    attr_reader :new_data&#xA;    &#xA;    def initialize(data)&#xA;        @new_data = transform(data)&#xA;    end&#xA;&#xA;    def do_something&#xA;        new_data.each do |item| &#xA;            # now we are able to reference easily understandable &#xA;            # property names (rather than item[0], item[1])&#xA;            puts item.coord_x&#xA;            puts item.coord_y&#xA;            puts &#39;---&#39;&#xA;        end&#xA;    end&#xA;&#xA;    Transform = Struct.new(:coord_x, :coord_y)&#xA;    &#xA;    def transform(data)&#xA;        data.collect { |item| Transform.new(item[0], item[1]) }&#xA;    end&#xA;end&#xA;&#xA;obj = MyClass.new([[10, 25],[3, 9],[41, 7]])&#xA;obj.do_something&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;single-responsibility-principle&#34;&gt;Single Responsibility Principle&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You should refactor your methods so they do one thing (also known as the &amp;lsquo;Single Responsibility Principle&amp;rsquo;). One reason to do this is so that your methods become easier to test, and also their new found simplicity can provide a greater clarity that can highlight whether other methods within the class should even be there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for example, you may have a complex algorithm contained within a single method of your class and because of its complexity you may miss the fact that some of the algorithm should actually have been handled by a separate class altogether.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Following the Single Responsibility Principle will result in smaller (and greater number of) small sized methods. This result will encourage greater code reuse from yourself (as well as other users of your code) and will also make your methods easier to test and to move around into different classes.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;remove-comments&#34;&gt;Remove comments&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If a piece of code needs a comment then chances are you need to extract that code into a separate method. The name of the method should serve the same purpose as the comment once did. This isn&amp;rsquo;t always the case, but as part of your analysis you should reconsider any comments to ensure they are helpful or just noise.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;do-not-tightly-couple-your-code&#34;&gt;Do not tightly couple your code&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The best way to decouple your code is to manage your dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if you look at a class that utilises another class for some additional functionality, that secondary class has become the dependency. Also, if you use that dependency in multiple places and the class was to change in some way then consider how many places your class potentially could break or need to be updated?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, a class referencing the name of another class isn&amp;rsquo;t necessarily a major issue in itself (as the change of a class name can easily be rectified using a modern IDE find &amp;amp; replace feature), the bigger problem is from the lack of code reuse. Your method is tightly coupled to a specific class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some other things to look out for are:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;arguments passed to a method on the dependency class&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if the class name itself is hard coded then technically that is an area of concern as well because if the dependency class was renamed then your code which references the old name would need to be updated.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;even down to things like the order of the arguments could be considered a dependency.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Every dependency results in more brittle, tightly coupled code.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;facades&#34;&gt;Facades&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Do not let external dependencies permeate your code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One way to prevent this is to wrap any dependencies in a method so you can implement a facade over the original interface allowing it to match your own API.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, if your dependency had a method which required arguments to be sent in a specific order then you could wrap the call to the method in a facade which allowed the user of your class to pass in the arguments in another format. Your facade could then normalise the data before passing it over to the dependency&amp;rsquo;s method.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;dependency-directions&#34;&gt;Dependency Directions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Make sure you spend time considering the direction of your dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When considering the direction of your dependencies (e.g. does class A rely more on class B, or vice versa) remember to think about the following 3 points&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;p&gt;Some classes are more likely to change than others&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Concrete classes are more likely to change than abstract classes.&lt;br&gt;&#xA;Imagine you have a class with a hard coded reference to another class. We could make the primary class more abstract by injecting the  dependency of the secondary class rather than having to reference it directly. This way the primary class is able to accept an object successfully as long as it implements the required method.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;A class with many dependants could result in widespread consequences.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 id=&#34;summary-of-dependencies&#34;&gt;Summary of dependencies&amp;hellip;&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;Dependency management is core to creating future-proof applications.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Injecting dependencies creates loosely coupled objects that can be reused.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Isolating dependencies allows objects to adapt to unexpected changes.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Depending on abstractions decreases the likelihood of facing changes.&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;The key to managing dependencies is to control their direction.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;And to quote another&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;ldquo;Depend on things that change less often than you do&amp;rdquo;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;flexible-interfaces&#34;&gt;Flexible Interfaces&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Object-Oriented applications are made up of objects(classes) but are defined by the messages that pass between these objects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our code must handle&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What objects &lt;em&gt;know&lt;/em&gt; (i.e. their responsibility)&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Who&lt;/em&gt; they know (i.e. their dependencies)&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;How&lt;/em&gt; they talk to one another&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;and this is done via our object&amp;rsquo;s interfaces.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Creating a flexible interface is essential to good Object-Oriented design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each object should reveal as little about itself, and know as little about other objects as possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are two parts to our interfaces: a Public Interface and a Private Interface&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;public-interface&#34;&gt;Public interface:&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Should reveal the primary responsibility&lt;/li&gt;&#xA;&lt;li&gt;Is expected to be invoked by others&lt;/li&gt;&#xA;&lt;li&gt;Will be unlikely to change (so safe for other objects to depend on)&lt;/li&gt;&#xA;&lt;li&gt;Testable&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3 id=&#34;private-interface&#34;&gt;Private interface&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Should handle implementation details&lt;/li&gt;&#xA;&lt;li&gt;Not be accessible by other objects&lt;/li&gt;&#xA;&lt;li&gt;Can be changed at anytime without causing side effects for other objects&lt;/li&gt;&#xA;&lt;li&gt;Aren&amp;rsquo;t even accessible by unit tests&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A good way to start designing your interfaces is to draw sequence diagrams (one way to do this is to use UML). Just remember to focus on the messages needing to be sent between objects rather than focusing on the objects themselves.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When designing your interfaces you should ask yourself the question: &amp;ldquo;I need to send this message, who should respond to it?&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to understand that you don&amp;rsquo;t send messages because you have objects. You have objects because you send messages. If you keep that in mind then you can ensure your objects only handle responsibilities relevant to them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Avoid asking the question &amp;ldquo;What should this class do?&amp;rdquo; and make sure your interfaces are designed in such a way that they ask for what they want and don&amp;rsquo;t try to tell another object what to do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, If you have a Mechanic class and you want the class to prepare a bike for you then don&amp;rsquo;t call the Mechanic&amp;rsquo;s individual methods: &amp;ldquo;clean_bike&amp;rdquo;, &amp;ldquo;pump_tyres&amp;rdquo;, &amp;ldquo;check_brakes&amp;rdquo; directly. Instead you know the message you want to send (in this case you want to have a bike prepared for you) so create an interface that supports that message requirement. Do this by creating a method on the Mechanic class called &amp;ldquo;prepare_bike&amp;rdquo; and send your message to that method. This way if the Mechanic class changes its implementation then the object that calls the &amp;ldquo;prepare_bike&amp;rdquo; method doesn&amp;rsquo;t have to change as well.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;reducing-context&#34;&gt;Reducing Context&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The things an object knows about other objects make up its &amp;lsquo;context&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An object may have a single responsibility but it expects a context. For example the object expects an object to respond to a specific method call.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For an object to become more reusable and more easily testable it must reduce its contexts. If there is a context then to reuse the object you need to bring along the context every time (this makes code reuse and testing harder).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Dependency injection reduces the context. For example if you had an object which called a generic method and passed &amp;lsquo;self&amp;rsquo; as an argument then the receiving object could handle the request (and because the first object was injected as a dependency) then the second object could call the first object when it&amp;rsquo;s finished with the request.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;summary-of-interfaces&#34;&gt;Summary of Interfaces&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Your interface defines your application and determines its future.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Object-Oriented applications are defined by messages that pass between objects. This is handled via public interfaces. Ask for what you want and don&amp;rsquo;t include any &amp;lsquo;hows&amp;rsquo; as part of the request which would be telling the receiving object how to behave rather than it handling the how itself.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;duck-typing&#34;&gt;Duck Typing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Duck Typing is the process of making code more flexible and less tightly coupled by taking into consideration that if an object &amp;ldquo;sounds like a duck, and quacks like a duck&amp;rdquo; then it stands to reason the object must indeed be (or act like) a duck.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The principle idea behind Duck Typing is to trust your objects (e.g. do not worry about the class of an object, only that the object implement the expected interface - and trust that it does). Sounds scary/dangerous but it will help you to avoid writing code that tightly couples to your dependencies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Cleaning up a long and ugly switch/case statement which checks the class of an object to determine what action to take is one area where Duck Typing can help. The problem with this example is that the switch statement technique is fragile and likely to break when new class types need to be added.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead, for each object create a generically named method (same name for each object) which handles the appropriate internal/specific details relevant for that object. This way you can just call the method (and even pass the calling object as a reference &lt;code&gt;self&lt;/code&gt; in case the receiving object needs further information to carry out its work) and thus make your code more reusable by not tightly coupling a specific method to multiple object calls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Also, any where you see the use of &lt;code&gt;is_a?&lt;/code&gt; or &lt;code&gt;responds_to?&lt;/code&gt; then that is an indication of a potential code smell because the principle issue identical to the switch statement.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;inheritance&#34;&gt;Inheritance&lt;/h2&gt;&#xA;&#xA;&lt;h3 id=&#34;abstract-your-base-class&#34;&gt;Abstract your base class&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When inheriting from another class it is essential that the parent class is as abstract as possible. For example, it only holds enough code that is relevant for all its sub classes. A sub class should never inherit redundant data or methods. If it does then your parent class isn&amp;rsquo;t abstract enough.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;default-values&#34;&gt;Default values&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Be careful when using default values. If your base class has a common property which is different for each sub class, but is required within each sub class (hence sticking it in the base class) then you won&amp;rsquo;t want to give it a value inside the base class. Your base class should take in the value via the constructor and if the value isn&amp;rsquo;t provided you should set the default using a method like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;xxx = args[:xxx] || default_xxx_value&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this example &lt;code&gt;default_xxx_value&lt;/code&gt; should be a method the sub class implements which provides the specific value. The reason we have written it like this is so that the sub class has better control over setting the default value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So far so good. But if a new user doesn&amp;rsquo;t read the documentation (which states they must implement &lt;code&gt;default_xxx_value&lt;/code&gt; within their sub class) then they will get an error thrown. In the above example it may be best to raise your own descriptive error by implementing the &lt;code&gt;default_xxx_value&lt;/code&gt; method as an abstract method within the base class like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def default_xxx_value&#xA;    raise NotImplementedError, &amp;quot;#{self.class} cannot respond to: &amp;quot;&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: the above custom error message raised will display automatically the name of the method (&lt;code&gt;default_xxx_value&lt;/code&gt;) at the end of the message when it is displayed to the user (hence we don&amp;rsquo;t need to manually include it).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;super&#34;&gt;Super&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Beware calls to &lt;code&gt;super&lt;/code&gt; via a sub class, as this is a code smell.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why? Because it declares that the sub class knows the implementation of the base class. It says &amp;ldquo;I know what you do, I know what to send to you and I know what returned value to expect&amp;rdquo;. The sub class has more context than it should do and we&amp;rsquo;ve created a dependency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this example the sub class knows too much about the base class and so it is tightly coupled to it. If a new developer joins the project and creates a sub class, but doesn&amp;rsquo;t call &lt;code&gt;super&lt;/code&gt; at the appropriate time, then they would likely have a silent failure (or at least one that could be difficult to debug).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To resolve the concern of using &lt;code&gt;super&lt;/code&gt; we can use a &amp;lsquo;hook message&amp;rsquo; which effectively allows the sub class to stay decoupled from the base class. The sub class needs to be able to trust that the base class will do the right thing (which in this case is to call a method).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way the hook method works is you remove the constructor from the sub class and move the sub class specific constructor code into a separate method of the sub class called &lt;code&gt;post_initialise&lt;/code&gt; (or whatever you want to call it). The base class&amp;rsquo; own constructor will be run when a new instance of the sub class is created but now the base class constructor will be updated so it calls the &lt;code&gt;post_initialise&lt;/code&gt; method at the end of its constructor (this means the base class needs to implement an empty &lt;code&gt;post_initialise&lt;/code&gt; method which the sub class then overwrites).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the sub class doesn&amp;rsquo;t know about the base class other than it inherits from it and the interface contract between them states the base class will at some point call &lt;code&gt;post_initialise&lt;/code&gt; whenever it&amp;rsquo;s ready to do so and the sub class takes over from there. It&amp;rsquo;s now clear that the sub class is just a specialised version of the base class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This works with other methods not just the constructor. The base class could have&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def spares&#xA;    { tyre_size:tyre_size }.merge(local_spares)&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;the sub class can then implement its own &lt;code&gt;local_spares&lt;/code&gt; method which returns a hash. So when a user creates a new instance of the sub class and calls the &lt;code&gt;spares&lt;/code&gt; method, the base class handles the functionality. The sub class can insert its own specialised data without knowing how the base class works (other than the interface design dictates the sub class should implement a method called &lt;code&gt;local_spares&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;modules&#34;&gt;Modules&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Not all objects are specialised versions of another object and so they shouldn&amp;rsquo;t always inherit functionality via the inheritance pattern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Objects have a tendency to play a role, and some objects play a similar role to other objects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of the inheritance pattern we can use modules as &amp;lsquo;mixins&amp;rsquo; which will let these objects (those with similar roles) share behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Modules are placed inside the same lookup path as methods acquired through inheritance, so the principles for developing modules should follow those of writing classes: use the Template Method Pattern (e.g. have stub methods which the sub classes overwrite).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, any object which includes the module needs to provide their own specialisation of a hook method implemented in the module. This means an object which includes the module doesn&amp;rsquo;t have to create a dependency by calling &lt;code&gt;super&lt;/code&gt;, thus avoiding needing to know anything about the included module (other than its implied interface contract) and ultimately reducing its context (i.e. what it knows - a dumb object is a reusable object).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;composition&#34;&gt;Composition&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The composition pattern is effectively the same as using modules (where you copy in functionality rather than inheriting it - thus creating a &amp;lsquo;&lt;em&gt;has-a&lt;/em&gt;&amp;rsquo; relationship rather than a &amp;lsquo;&lt;em&gt;is-a&lt;/em&gt;&amp;rsquo; relationship).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But composition from a design perspective is more about the resulting &amp;lsquo;whole&amp;rsquo;, than the subsequent parts that make up the whole.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;inheritance-vs-composition&#34;&gt;Inheritance vs Composition&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Inheritance is the more appropriate solution if your design dictates that the objects have a well defined concrete class of functionality and that most of that base functionality is the same for all other objects. With inheritance you would write only small amounts of new code to extend the base functionality so the extending objects become more specialised.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Inheritance is specialisation&lt;br&gt;&#xA;&lt;em&gt;Bertrand Meyer, Touch of Class&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If on the other hand your objects are all different and the design of the objects dictates there could be multiple reusable &amp;lsquo;parts&amp;rsquo;, then composition would be the better solution.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Use composition when the behaviour is more than the sum of it&amp;rsquo;s parts&lt;br&gt;&#xA;&lt;em&gt;Grady Booch, Object-Oriented Analysis and Design&lt;/em&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2 id=&#34;further-good-rules-of-development-from-sandi-metz&#34;&gt;Further good rules of development from Sandi Metz&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Your class can be no longer than a hundred lines of code.&lt;/li&gt;&#xA;&lt;li&gt;Your methods can be no longer than five lines of code&lt;/li&gt;&#xA;&lt;li&gt;You can pass no more than four parameters (do not make it one big hash either).&lt;/li&gt;&#xA;&lt;li&gt;In your controller, you can only instantiate one object, to do whatever it is that needs to be done.&lt;/li&gt;&#xA;&lt;li&gt;Your view can only know about one instance variable.&lt;/li&gt;&#xA;&lt;li&gt;Rules are meant to be broken if by breaking them you produce better code. [ &amp;hellip;where &amp;ldquo;better code&amp;rdquo; is validated by explaining why you want to break the rule to someone else. ]&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So just to quickly recap on some of the important points covered&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Decouple your code&lt;/li&gt;&#xA;&lt;li&gt;Describe your class to see if it does too much&lt;br&gt;&#xA;e.g. for each class write down a single line description and try to avoid the words &amp;lsquo;and&amp;rsquo;, &amp;lsquo;or&amp;rsquo; from occuring&lt;/li&gt;&#xA;&lt;li&gt;Review each method thoroughly (you may find some methods don&amp;rsquo;t belong in your class and deserve their own interface)&lt;/li&gt;&#xA;&lt;li&gt;Manage your dependencies:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Check the method arguments you&amp;rsquo;re passing around&lt;/li&gt;&#xA;&lt;li&gt;Use dependency injection (don&amp;rsquo;t hard code class names)&lt;/li&gt;&#xA;&lt;li&gt;Avoid direct references to complex data structures (transform your data into a more appropriate form)&lt;/li&gt;&#xA;&lt;li&gt;Abide by the Single Responsibility Principle (SRP)&lt;/li&gt;&#xA;&lt;li&gt;Review comments to ensure their purpose and usefulness&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Your commented coded could be better handled by moving into a separate method with a descriptive name&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Write more flexible interfaces:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Object-Oriented code is more about the &amp;lsquo;messages&amp;rsquo; sent between objects than the objects themselves&lt;/li&gt;&#xA;&lt;li&gt;Think about the messages you want to send and create objects/interfaces to handle them&lt;/li&gt;&#xA;&lt;li&gt;Ask for what you &lt;em&gt;want&lt;/em&gt; and don&amp;rsquo;t include &lt;em&gt;how&lt;/em&gt; to do what you want&lt;/li&gt;&#xA;&lt;li&gt;Ensure messages you send (e.g. method calls you make) don&amp;rsquo;t rely on knowledge of the object that implements the method&lt;/li&gt;&#xA;&lt;li&gt;Reduce your object&amp;rsquo;s context (i.e. how much it knows about other objects). Dependency Injection can help here&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Trust your objects (e.g. Duck Typing design principles)&lt;/li&gt;&#xA;&lt;li&gt;If using the inheritance pattern:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Abstract your shared functionality into the base class&lt;/li&gt;&#xA;&lt;li&gt;Make sure sub classes inherit only what they need&lt;/li&gt;&#xA;&lt;li&gt;Avoid calling &lt;code&gt;super&lt;/code&gt; as it&amp;rsquo;s a code smell&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/design-oop/</guid>
      <link>https://www.integralist.co.uk/posts/design-oop/</link>
      <pubDate>Tue, 12 Feb 2013 00:00:00 +0000</pubDate>
      <title>Object Oriented Design</title>
    </item>
    <item>
      <description>&lt;p&gt;I thought I would get down in a blog post the different &lt;a href=&#34;http://git-scm.com&#34; target=&#34;_blank&#34;&gt;Git&lt;/a&gt; commands and tips that I find really useful, because every now and then it seems I need to refer back to these notes (which up until this point have been in a txt file in my Dropbox) if I&amp;rsquo;ve not used a particular command in a while.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hopefully you&amp;rsquo;ll find them useful too.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;show-where-git-is-installed&#34;&gt;Show where Git is installed&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;which git&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;show-the-git-version-installed&#34;&gt;Show the Git version installed&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git version&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;update-your-global-user-details&#34;&gt;Update your global user details&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global user.name &amp;quot;Your Name&amp;quot;&#xA;git config --global user.email &amp;quot;Your Email&amp;quot;&#xA;git config --global apply.whitespace nowarn # ignore white space changes!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;set-up-a-global-ignore-file&#34;&gt;Set-up a global ignore file&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First create the global ignore file…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;touch ~/.gitignore_global&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Then add the following content to it (&lt;em&gt;this is a standard ignore file but I&amp;rsquo;ve added some Sass CSS pre-processor files to it&lt;/em&gt;)…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;# Compiled source #&#xA;###################&#xA;*.com&#xA;*.class&#xA;*.dll&#xA;*.exe&#xA;*.o&#xA;*.so&#xA;*.sass-cache&#xA;*.scssc&#xA;&#xA;# Packages #&#xA;############&#xA;# it&#39;s better to unpack these files and commit the raw source&#xA;# git has its own built in compression methods&#xA;*.7z&#xA;*.dmg&#xA;*.gz&#xA;*.iso&#xA;*.jar&#xA;*.rar&#xA;*.tar&#xA;*.zip&#xA;&#xA;# Logs and databases #&#xA;######################&#xA;*.log&#xA;*.sql&#xA;*.sqlite&#xA;&#xA;# OS generated files #&#xA;######################&#xA;.DS_Store&#xA;.DS_Store?&#xA;._*&#xA;.Spotlight-V100&#xA;.Trashes&#xA;Icon?&#xA;ehthumbs.db&#xA;Thumbs.db&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can let Git know about your global ignore file by editing your global &lt;code&gt;.gitconfig&lt;/code&gt; file…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;nano ~/.gitconfig&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…then adding the following to it…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[core]&#xA;    excludesfile = /Users/&amp;lt;home-directory&amp;gt;/.gitignore_global&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…or once the &lt;code&gt;.gitignore_global&lt;/code&gt; file is created you can just tell git by using this short-hand command…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git config --global core.excludesfile ~/.gitignore_global&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;adding-all-files-inc-those-marked-as-deleted&#34;&gt;Adding all files (inc. those marked as deleted)&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git add -A&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;writing-a-long-commit&#34;&gt;Writing a long commit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A short git commit message would look like this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git commit -m &amp;quot;My short commit message&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…but you should really be writing longer more descriptive commit messages which you do like so:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git commit&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…what this does is open up the default editor for commit messages (which for most is Vim). Now Vim is a bizarre editor with all sorts of odd shortcuts for adding text. I&amp;rsquo;ve only used Vim to write commit messages (nothing else) so I have a very focused set of commands to write my commands…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Press &lt;code&gt;i&lt;/code&gt; which puts Vim into &amp;lsquo;insert&amp;rsquo; mode (meaning you can actually write)&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;This is my short description for this commit&#xA;- Here is a break down of my changes&#xA;- Another note about a particular change&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;After I&amp;rsquo;ve written my commit I just need to save the commit and exit Vim…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Press &lt;code&gt;Esc&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Press &lt;code&gt;:wq&lt;/code&gt; (the colon means you can execute more commands, w = write, q = quit)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;viewing-file-changes-while-writing-your-commit&#34;&gt;Viewing file changes while writing your commit&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git commit -v&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;viewing-what-files-have-been-committed&#34;&gt;Viewing what files have been committed&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git ls-files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;improving-git-log-with-git-lg&#34;&gt;Improving &lt;code&gt;git log&lt;/code&gt; with &lt;code&gt;git lg&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To get a better looking &lt;code&gt;git log&lt;/code&gt; we need to write an alias called &lt;code&gt;git lg&lt;/code&gt; that is just made up of standard Git commands/flags but when put together (along with specific colour settings) means we can have a short git command that provides us lots of useful information.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What we need to do is open the &lt;code&gt;~/.gitconfig&lt;/code&gt; file and then add the following content…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[alias]&#xA;    lg = log --color --graph \&#xA;    --pretty=format:&#39;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset&#39; \&#xA;    --abbrev-commit --date=relative&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;shorter-git-status&#34;&gt;Shorter &lt;code&gt;git status&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As per the above tip, we can create two extra alias&amp;rsquo; which give us a shorter command to type (I don&amp;rsquo;t know about you but when typing really fast I seem to always misspell the word &amp;lsquo;status&amp;rsquo;) and doesn&amp;rsquo;t show us all the unnecessary crap that someone new to Git needs to see.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What we need to do is open the &lt;code&gt;~/.gitconfig&lt;/code&gt; file and then add the following content…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[alias] &#xA;    st = status&#xA;    sts = status -sb&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…you don&amp;rsquo;t need to specify &lt;code&gt;[alias]&lt;/code&gt; if it&amp;rsquo;s already in the file (see previous tip).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now typing &lt;code&gt;git st&lt;/code&gt; will be the same as &lt;code&gt;git status&lt;/code&gt;, and typing &lt;code&gt;git sts&lt;/code&gt; will be the same as &lt;code&gt;git status -sb&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;finding-a-commit-that-includes-a-specific-phrase&#34;&gt;Finding a commit that includes a specific phrase&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git log --grep=&amp;lt;your-phrase-here&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git log --grep=CSS&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;will display all commits that contain the word &amp;lsquo;CSS&amp;rsquo; in the message.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;only-merging-the-files-you-want&#34;&gt;Only merging the files you want&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout &amp;lt;branch-name&amp;gt; &amp;lt;file1&amp;gt; &amp;lt;file2&amp;gt; &amp;lt;file3&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;stashing-changes-you-re-not-ready-to-commit&#34;&gt;Stashing changes you&amp;rsquo;re not ready to commit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you make changes to your branch and then want to quickly change branches without first having to commit your current &amp;lsquo;dirty state&amp;rsquo; then run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To apply a stashed state (git assumes the most recent stashed state if none specified) use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash apply&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To see which stashes you&amp;rsquo;ve stored (on any branch) use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash list&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When viewing a list of stashes it can be useful if the stashes had corresponding messages (so you know what each stash holds), for that to happen you&amp;rsquo;ll need to create stashes with an associated message using the &lt;code&gt;save&lt;/code&gt; command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash save &amp;quot;my message here&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you have multiple stashes under a branch (e.g. &lt;code&gt;stash@{1}&lt;/code&gt; &lt;code&gt;stash@{2}&lt;/code&gt; &lt;code&gt;stash@{3}&lt;/code&gt;) then you can reference a particular stash using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash apply stash@{2}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;pre git &lt;code&gt;2.0&lt;/code&gt; the following would work &lt;code&gt;git stash apply@{2}&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;If you want to stash only specific changes then use the patch mode:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash -p&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To view the contents of a stash use:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash show -p stash@{n}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;with the &lt;code&gt;-p&lt;/code&gt; to &lt;em&gt;print&lt;/em&gt; the output of the files, the &lt;code&gt;show&lt;/code&gt; subcommand would simply print the filenames.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;…where &amp;lsquo;n&amp;rsquo; is the numeric index of the stash (you can also use &lt;code&gt;git show stash@{n}&lt;/code&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Applying the stash doesn&amp;rsquo;t mean it&amp;rsquo;s removed from your list of stashes though(!) so you need to run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash drop stash@{&amp;lt;index&amp;gt;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash drop stash@{2}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also apply and drop the stash at the same time:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash pop&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also specify an exact stash to pop:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash pop stash@{2}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you stash some work, leave it there for a while, and continue on the branch from which you stashed the work, you may have a problem reapplying the work. If the apply tries to modify a file that you’ve since modified, you’ll get a merge conflict and will have to try to resolve it. If you want an easier way to test the stashed changes again, you can run &lt;code&gt;git stash &amp;lt;branch&amp;gt;&lt;/code&gt; which creates a new branch for you, checks out the commit you were on when you stashed your work, reapplies your work there, and then drops the stash if it applies successfully.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you need to stash only specific files then first &lt;code&gt;git add&lt;/code&gt; the files you don&amp;rsquo;t want to stash, then run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git stash --keep-index&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&amp;hellip;finally you can then &lt;code&gt;git reset&lt;/code&gt; the files you originally added (if you don&amp;rsquo;t plan on committing them yet).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;revert-all-changes-back-to-last-commit&#34;&gt;Revert all changes back to last commit&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git reset --hard&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: you can do a &amp;lsquo;soft&amp;rsquo; reset &lt;code&gt;git reset --soft &amp;lt;hash&amp;gt;&lt;/code&gt;. The difference between &lt;code&gt;--hard&lt;/code&gt; and &lt;code&gt;--soft&lt;/code&gt; is with &lt;code&gt;--hard&lt;/code&gt; the specified commit hash&amp;rsquo;s files are moved into the working directory and the staging area (as if there were no changes since that specified commit). But using &lt;code&gt;--soft&lt;/code&gt; will leave whatever changes you&amp;rsquo;ve made in your working directory/staging area but will restore the specified commit you&amp;rsquo;ve selected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine you have a file called &lt;code&gt;foo.txt&lt;/code&gt; and your Git history looked like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;A -&amp;gt; B -&amp;gt; C (HEAD)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s see each commit we made:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;A == foo&#xA;B == FOO&#xA;C == Foo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following examples explain the different reset flags:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git reset --soft B  == move HEAD to B but keep C&#39;s changes staged (i.e. added to the index)&#xA;&#xA;git reset --mixed B == move HEAD to B but keep C&#39;s changes unstaged&#xA;&#xA;git reset --hard B  == move HEAD to B but completely delete C (you&#39;ve lost those changes forever)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;to undo a &lt;code&gt;reset&lt;/code&gt; use &lt;code&gt;git reflog&lt;/code&gt; to find the previous state (e.g. &lt;code&gt;HEAD@{1}&lt;/code&gt;) and then reset again (e.g. &lt;code&gt;git reset HEAD@{1}&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;unstaging-files&#34;&gt;Unstaging files&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To unstage files we&amp;rsquo;ve added to the staging area we need to run the command &lt;code&gt;reset HEAD&lt;/code&gt; but that&amp;rsquo;s a bit ugly and awkward to remember. What would be easier is if we could just say &lt;code&gt;git unstage&lt;/code&gt;, so let&amp;rsquo;s create an alias to help make that easier!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Open up the file &lt;code&gt;~/.gitconfig&lt;/code&gt; and then add the following content…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;[alias]&#xA;    unstage = reset HEAD&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: you don&amp;rsquo;t need to specify &lt;code&gt;[alias]&lt;/code&gt; if it&amp;rsquo;s already in the &lt;code&gt;~/.gitconfig&lt;/code&gt; file.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also unstage a single file using:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git reset &amp;lt;file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;ve staged files before any commits have been set (e.g. right at the start of your project) then you&amp;rsquo;ll find the above wont work because technically there are no commits to revert back to. So instead you&amp;rsquo;ll need to remove the files like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rm --cached &amp;lt;file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;you might need to replace &lt;code&gt;--cached&lt;/code&gt; with &lt;code&gt;--staged&lt;/code&gt; in newer versions of git.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;untrack-a-file-without-deleting-it&#34;&gt;Untrack a file without deleting it&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you want to have Git stop tracking a file it&amp;rsquo;s already tracking then you would think to run:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rm &amp;lt;file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…but the problem with that command is that Git will also delete the file altogether!? Something we usually don&amp;rsquo;t want to have happen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The work around to that issue is to use the &lt;code&gt;--cached&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rm --cached &amp;lt;file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;amend-your-last-commit&#34;&gt;Amend your last commit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you make a commit and then realise that you want to amend the commit message then don&amp;rsquo;t make any changes to the files and just run…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git commit --amend&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…which will open up the default editor for handling commits (usually Vim) and will let you amend the commit message.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If on the other hand you decide that after you&amp;rsquo;ve written a commit that you want to amend the commit by adding some more files to it then just add the files as normal and run the same command as above and when Vim opens to let you edit the commit message you&amp;rsquo;ll see the extra files you added as part of that commit.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;show-the-files-within-a-commit&#34;&gt;Show the files within a commit&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git show &amp;lt;hash&amp;gt; --name-only&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;see-differences-between-files&#34;&gt;See differences between files&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To see the difference between the current working directory and the last commit:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If your files have been added to the staging area already then you can use the &lt;code&gt;--cached&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff --cached&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the use of &lt;code&gt;--cached&lt;/code&gt; has now been replaced with the more appropriate &lt;code&gt;--staged&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To show specific changes use the &lt;code&gt;--word-diff&lt;/code&gt; flag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff --word-diff&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To see the diff between the working directory and a specific commit:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff &amp;lt;hash&amp;gt; &amp;lt;file-name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;the file name is optional&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;To see the difference between branches:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff &amp;lt;branch-1&amp;gt;..&amp;lt;branch-2&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;see-changes-between-two-commits&#34;&gt;See changes between two commits&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git diff &amp;lt;more-recent-hash&amp;gt; &amp;lt;older-hash&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;creating-a-branch-and-moving-to-it-at-the-same-time&#34;&gt;Creating a branch and moving to it at the same time&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout -b &amp;lt;branch-name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;deleting-a-branch&#34;&gt;Deleting a branch&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git branch -D &amp;lt;branch-name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;viewing-all-branches-of-a-remote&#34;&gt;Viewing all branches of a remote&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git branch -a&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;checkout-a-remote-branch&#34;&gt;Checkout a remote branch&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What normally happens is this: you clone down a repository from GitHub and this repo will have multiple branches, but if you run &lt;code&gt;git branch&lt;/code&gt; locally all you see is the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you run &lt;code&gt;git branch -a&lt;/code&gt; you can see all the branches for that remote repository but you just can&amp;rsquo;t access them or check them out?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you want to access the other branches within that repo then run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout -b &amp;lt;new-local-branch-name&amp;gt; origin/&amp;lt;remote-branch-name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…this will create a new branch named whatever you called it and contains the content of the remote branch you specified.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;remove-a-remote&#34;&gt;Remove a remote&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git remove rm &amp;lt;remote&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;revert-a-specific-file-back-to-an-earlier-version&#34;&gt;Revert a specific file back to an earlier version&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git checkout &amp;lt;hash|tag|HEAD&amp;gt; &amp;lt;file-name&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note if you&amp;rsquo;ve staged your file and then started making changes to the file which you no longer want applied you can use: &lt;code&gt;git checkout -- &amp;lt;file-name&amp;gt;&lt;/code&gt; to revert to the version of the file in the staging area.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;viewing-all-commits-for-a-file-and-who-made-those-changes&#34;&gt;Viewing all commits for a file and who made those changes&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git blame &amp;lt;file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;viewing-complete-history-of-a-file-even-when-deleted&#34;&gt;Viewing complete history of a file (even when deleted)&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git log --full-history  -- &amp;lt;path/to/file&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To see the last change you’d use a negative numeral like so &amp;ndash;full-history -1 and that should indicate when/where the file was deleted.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;if you didn’t use &lt;code&gt;--full-history&lt;/code&gt; I believe that git gives you a &lt;em&gt;modified&lt;/em&gt; version of its history where the deleted file doesn’t even show up (e.g. if you had done &lt;code&gt;git log -- &amp;lt;path/to/file&amp;gt;&lt;/code&gt;).&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;commiting-only-parts-of-a-file-rather-than-the-whole-file&#34;&gt;Commiting only parts of a file rather than the whole file&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have a file with lots of changes made, you might not want to have all the changes logged under one single commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To split the single file into multiple commits you need to use Git&amp;rsquo;s &lt;code&gt;patch&lt;/code&gt; mode…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git add &amp;lt;file&amp;gt; -p&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…Git will attempt to split a file into separate hunks (Git terminology for a chunk of code). You can then press &lt;code&gt;?&lt;/code&gt; to see what options you have available, the most common being:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;y&lt;/code&gt; - yes&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;n&lt;/code&gt; - no&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;d&lt;/code&gt; - no to all remaining hunks&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;s&lt;/code&gt; - split current hunk into more hunks&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Sometimes you can&amp;rsquo;t split a hunk into more hunks automatically, you have to do it manually. To do so you press &lt;code&gt;e&lt;/code&gt; to edit and then use Vim to manually make changes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So if you have a line removed that you want to keep as part of the commit then you&amp;rsquo;ll remove the &lt;code&gt;-&lt;/code&gt; so there is just a space instead, and if you have a line added that you want to not have included as part of the commit then you remove the entire line. BUT the most important part it also updating the line numbers at the top of the file so that the number of lines in the file match what you are looking to commit (otherwise the commit will fail). To make the edit to the hunk final (pre-commit) press &lt;code&gt;esc&lt;/code&gt; then &lt;code&gt;:wq&lt;/code&gt; and then you&amp;rsquo;ll be able to commit the selected changes.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;modifying-your-git-history-with-rebase&#34;&gt;Modifying your Git history with &lt;code&gt;rebase&lt;/code&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To change multiple commits you must use the interactive mode of the &lt;code&gt;rebase&lt;/code&gt; command and you must tell Git how many commits back you want to go (because it&amp;rsquo;ll start from there and keep moving through the commits until it reaches the &lt;code&gt;HEAD&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;REMEMBER: when using &lt;code&gt;rebase&lt;/code&gt; every commit in the range specified is changed whether you change the message or not. So don&amp;rsquo;t use &lt;code&gt;rebase&lt;/code&gt; on commits that have already been pushed to a remote server as other users might have those commits pulled down and your changing of the commits will cause havoc for those users in the near future.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To amend the last 3 commits we use: &lt;code&gt;git rebase -i HEAD~3&lt;/code&gt; and follow the instructions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The principle is if you want to merge two commits then you&amp;rsquo;ll need to have a commit to merge into and then change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;squash&lt;/code&gt; on the other commits that you want to have squashed into the previous commit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can also re-order commits and other things like change commits (add files, rename the message) and remove commits completely.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;push-branch-without-specifying-its-name&#34;&gt;Push branch without specifying its name&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you have a long branch name then you&amp;rsquo;ll know how tedious it is to type out:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git push origin bug-fix/cache-nodes-expiration&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Instead you can rely on the fact that git will retrieve the current branch name from its head tag:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git push origin head&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;display-verbose-branch-information&#34;&gt;Display verbose branch information&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git branch -vv&#xA;&#xA;* integralist/foo     58a472b6e3a bump minor version&#xA;  integralist/bar     fc5184faaf3 no-op this service to see if anyone or anything complains&#xA;  integralist/baz     23a273f7001 move from timing metric to distribution&#xA;  master              d0cd3e3a334 [origin/master] 5.0.0 - remove write_stats (#57413)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;display-concise-status-information&#34;&gt;Display concise status information&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git status -sb&#xA;&#xA;## master...origin/master&#xA; M content/posts/git-tips.md&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;staged-files-that-were-never-commited&#34;&gt;Staged files that were never commited&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git fsck --lost-found&#xA;&#xA;Checking object directories: 100% (256/256), done.&#xA;&#xA;dangling blob 0d80705a8f09dbc9ef0dd9f5799061b9ec9c0f05&#xA;dangling commit 20e04d00aa1eba1d0f19fa7d1865c6a011715288&#xA;dangling blob 49c0238e07d183407466c54f8ac5f7aa89889ae2&#xA;dangling blob 5380475369f22f6021d94c636ae4b778d3a0c050&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;div class=&#34;alert alert-note&#34;&gt;&lt;p class=&#34;alert-title&#34;&gt;ℹ️ NOTE&lt;/p&gt;&lt;p&gt;git will extract data to &lt;code&gt;.git/lost-found&lt;/code&gt;, use &lt;code&gt;--dangling&lt;/code&gt; instead of &lt;code&gt;--lost-found&lt;/code&gt; if you don&amp;rsquo;t want that to happen.&lt;/p&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Useful when &lt;code&gt;git reflog&lt;/code&gt; fails you (e.g. you executed &lt;code&gt;git reset --hard&lt;/code&gt; while uncommitted files were staged).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;finding-commit-that-introduced-a-bug&#34;&gt;Finding commit that introduced a bug&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git bisect start&#xA;git bisect bad           # to indicate current commit is broken&#xA;git bisect good &amp;lt;commit&amp;gt; # to indicate the last good commit&#xA;git bisect &amp;lt;bad|good&amp;gt;&#xA;git bisect reset&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;But you can also automate this by calling &lt;code&gt;git bisect run&lt;/code&gt; and passing a script:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git bisect run ./some-script&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you want to test specific directories and files then use &lt;code&gt;-- &amp;lt;dir&amp;gt;&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git bisect start -- ./sub_directory&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The bisect command uses a binary search which makes it very efficient, but if you want a linear search then you can use &lt;code&gt;git rebase&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git rebase -i --exec &amp;quot;./some-script&amp;quot; d294ae9&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Your script returning an error exit code will cause the rebase to stop on the commit that triggered the failure.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;finding-a-commit-that-added-removed-content&#34;&gt;Finding a commit that added/removed content&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;git log -S &amp;quot;bisect&amp;quot;&#xA;commit c38d5a5d7e5b32a8f6ef8d6ef2d84ad003537862&#xA;Author: Integralist &amp;lt;mark.mcdx@gmail.com&amp;gt;&#xA;Date:   Mon Mar 30 20:07:22 2020 +0100&#xA;&#xA;    git internals&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;If you&amp;rsquo;re looking for a change that doesn&amp;rsquo;t result in a new line being added/removed (e.g. a change to an &lt;em&gt;existing&lt;/em&gt; line), then you can use the &lt;code&gt;-G&lt;/code&gt; flag instead which will accept a regex pattern to search (see &lt;code&gt;man git-log&lt;/code&gt; for a useful example).&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/git-tips/</guid>
      <link>https://www.integralist.co.uk/posts/git-tips/</link>
      <pubDate>Sun, 16 Dec 2012 00:00:00 +0000</pubDate>
      <title>Git Tips</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve written this &lt;em&gt;very&lt;/em&gt; brief guide to JavaScript just as an aid for people new to the language and who need a basic starting point to see what the syntax looks like and to get a feeling for some of its features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This article&amp;rsquo;s main purpose is to give readers new to the language a glimpse of the JavaScript environment and to hopefully spur them onto further reading/learning.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-is-javascript&#34;&gt;What is JavaScript&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;JavaScript is a &lt;em&gt;scripting language&lt;/em&gt; - this means it is not &lt;em&gt;compiled&lt;/em&gt; (like traditional software languages like C or C++) but is executed &amp;lsquo;line by line&amp;rsquo; via its host environment at run time (the host environment can be: Web Browser, Server, Command Line, Desktop).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;terminology&#34;&gt;Terminology&lt;/h2&gt;&#xA;&#xA;&lt;table&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;th&gt;Term&lt;/th&gt;&#xA;        &lt;th&gt;Example&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;expression&lt;/td&gt;&#xA;        &lt;td&gt;An expression is a command that the JavaScript engine can &lt;em&gt;evaluate&lt;/em&gt; to produce a value&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;statement&lt;/td&gt;&#xA;        &lt;td&gt;A statement is a command that can be executed (statements are terminated with a semicolon)&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;identifier&lt;/td&gt;&#xA;        &lt;td&gt;A name (e.g. variable name, function name, labels for loops).&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;function declaration&lt;/td&gt;&#xA;        &lt;td&gt;&lt;code&gt;function myFunction(){ /* code */ }&lt;/code&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;function expression&lt;/td&gt;&#xA;        &lt;td&gt;&lt;code&gt;var myFunction = function(){ /* code */ };&lt;/code&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;primitive&lt;/td&gt;&#xA;        &lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt; and &lt;code&gt;number&lt;/code&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;operator&lt;/td&gt;&#xA;        &lt;td&gt;&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt;, &lt;code&gt;++&lt;/code&gt;, &lt;code&gt;===&lt;/code&gt;, &lt;code&gt;&amp;&amp;&lt;/code&gt;, &lt;code&gt;typeof&lt;/code&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h3 id=&#34;expressions&#34;&gt;Expressions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An example of an &amp;lsquo;expression&amp;rsquo; would be &lt;code&gt;1+1&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Looks straight forward enough, and it should be. As mentioned above, an expression is simply &lt;em&gt;something&lt;/em&gt; that can be interpreted as a value. So &lt;code&gt;1+1&lt;/code&gt; (when evaluated by the JavaScript engine) results in an number with a value of two.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now the expression &lt;code&gt;1+1&lt;/code&gt; is pretty useless in a JavaScript program because we&amp;rsquo;re not doing anything with it. For us to more effectively use this expression we ideally want to store it somewhere so we can reference it later and that&amp;rsquo;s where &amp;lsquo;variables&amp;rsquo; come in (see later on this article).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;statements&#34;&gt;Statements&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Examples of JavaScript &amp;lsquo;statements&amp;rsquo;:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;if (condition) { /* code */ }&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;while (condition) { /* code */ }&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;return&lt;/code&gt;, &lt;code&gt;break&lt;/code&gt;, &lt;code&gt;throw&lt;/code&gt; are single command statements&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 id=&#34;global-object&#34;&gt;Global Object&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When the JavaScript interpreter starts up it creates a Global object and any properties/methods added to the Global object are available to the entire JavaScript program.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The global object is a regular object (as per the Object section seen later in this article).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The global object is different depending on the context. In a web browser environment the global object is said to be the &lt;code&gt;window&lt;/code&gt; object. But this isn&amp;rsquo;t completely accurate. The global object happens to have a &lt;code&gt;window&lt;/code&gt; property which is set back to the global object itself! A little confusing I know :-) If you open a browser console (e.g. Firefox&amp;rsquo;s Firebug JavaScript Console, or Safari/Google Chrome&amp;rsquo;s Console Tool) and enter the command &lt;code&gt;window&lt;/code&gt; you&amp;rsquo;ll see all the properties/methods available on that object - things like &lt;code&gt;window.location&lt;/code&gt; will be one option that is listed (this references the location bar API of the web browser).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One quote you&amp;rsquo;ll hear a lot in JavaScript is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Don&amp;rsquo;t pollute the global environment&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;…and what this means is try to avoid creating global properties and methods. The less &amp;lsquo;globals&amp;rsquo; you create then the less likely your code will conflict with another piece of code written by someone else that may be included in the same page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To avoid declaring global properties/methods there are certain &amp;lsquo;patterns&amp;rsquo; that have been designed to work around this issue, such as the IIFE pattern…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/*&#xA; * this pattern is referred to as an IIFE (immediately invoked function expression)&#xA; * the function is immediately executed and all code within it is scoped to the function&#xA; * when executed we pass through &#39;this&#39; which refers to the global object&#xA; * we accept &#39;this&#39; into the function as an argument called &#39;global&#39;&#xA; */&#xA;var app = (function (global) {&#xA;&#xA;    // private data (private as in: it can&#39;t be accessed from other code outside this function)&#xA;    // note: don&#39;t EVER name your functions like this!&#xA;    function will_be_made_public_but_cant_be_accessed_directly(){&#xA;        console.log(&#39;Private&#39;);&#xA;    }&#xA;    &#xA;    return {&#xA;        // public API (private code we&#39;ve chosen to make public)&#xA;        do_something: will_be_made_public_but_cant_be_accessed_directly&#xA;    };&#xA;&#xA;}(this));&#xA;&#xA;// TypeError: Object #&amp;lt;Object&amp;gt; has no method &#39;will_be_made_public_but_cant_be_accessed_directly&#39;&#xA;app.will_be_made_public_but_cant_be_accessed_directly() &#xA;&#xA;app.do_something(); // =&amp;gt; &#39;Private&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Another pattern is to use AMD (Asynchronous Module Definition) which is a module based pattern (see: &lt;a href=&#34;https://github.com/Integralist/Blog-Posts/blob/master/Beginners-guide-to-AMD-and-RequireJS.md&#34; target=&#34;_blank&#34;&gt;Beginners guide to AMD and RequireJS&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;variables&#34;&gt;Variables&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Variables hold values/data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You declare a variable like so: &lt;code&gt;var my_var = 123;&lt;/code&gt; - in this example we&amp;rsquo;ve declared a variable and assigned the value &lt;code&gt;123&lt;/code&gt; to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You must always declare a variable. An undeclared variable looks like this: &lt;code&gt;my_var = 123;&lt;/code&gt; - notice the lack of the &lt;code&gt;var&lt;/code&gt; keyword.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Undeclared variables are a bad practice because they cause confusion as to whether the variable should be &amp;lsquo;global&amp;rsquo; or not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a break down of the different variable scenarios:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Variable is declared within a function:&lt;br&gt;&#xA;variable becomes scoped to that function (i.e. it isn&amp;rsquo;t accessible outside of that function).&lt;/li&gt;&#xA;&lt;li&gt;Variable is declared at the top level of the script file (e.g. not inside of a function):&lt;br&gt;&#xA;variable becomes a global variable (i.e. is available any where within the JavaScript program).&lt;/li&gt;&#xA;&lt;li&gt;Variable is undeclared (e.g. doesn&amp;rsquo;t matter where in the program the undeclared variable was created):&lt;br&gt;&#xA;variable becomes a global variable (i.e. is available any where within the JavaScript program).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As you can see, missing a &lt;code&gt;var&lt;/code&gt; declaration will mean the JavaScript engine will make that undeclared variable a &amp;lsquo;global&amp;rsquo; variable (e.g. it is assigned to the Global object).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To see why this is a problem first imagine you have a web page you&amp;rsquo;re working on and in which you have included a 3rd party JavaScript file (i.e. a script written by another developer). Now imagine the content of that 3rd party script is as follows:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// 3rd party script written by another developer...&#xA;var my_name = &#39;Mark&#39;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…in this instance, the 3rd party script hasn&amp;rsquo;t wrapped the line &lt;code&gt;var my_name = &#39;Mark&#39;;&lt;/code&gt; inside of an IIFE (see above pattern) so the variable &lt;code&gt;my_name&lt;/code&gt; will be created as global property (e.g. it is available any where within the JavaScript program as well as explicitly via &lt;code&gt;window.my_name&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now you don&amp;rsquo;t want to overwrite the variable &lt;code&gt;my_name&lt;/code&gt; because the 3rd party script that defined it is relying on it being a String with a value of &lt;code&gt;Mark&lt;/code&gt; - if you change the value then it could cause the 3rd party code to break.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So now imagine you&amp;rsquo;re going to add your own code to the page. You write the following…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function do_something(){&#xA;    my_name = &#39;Bob&#39;;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…this may cause unintended side effects on the 3rd party code. Why? Because you coincidentally defined a variable by the same name of &lt;code&gt;my_name&lt;/code&gt; and although you likely intended it to be scoped to the function &lt;code&gt;do_something&lt;/code&gt; you&amp;rsquo;ve accidentally forgotten the &lt;code&gt;var&lt;/code&gt; keyword and so your variable is undeclared, so your variable has been assigned to the Global object, thus overwriting the &lt;code&gt;my_name&lt;/code&gt; variable that is already available on the Global object (set by the 3rd party code).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To fix this you would simply make sure you properly declared your variable like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function do_something(){&#xA;    var my_name = &#39;Bob&#39;;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So now, even though the variable name is the same, the variable is &amp;lsquo;scoped&amp;rsquo; to the &lt;code&gt;do_something&lt;/code&gt; function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In today&amp;rsquo;s world you&amp;rsquo;ll be very hard pushed to find a library that sets anything more than one global variable - but it&amp;rsquo;s an issue to be aware of in case you inherit a code base from a less educated developer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Global properties aren&amp;rsquo;t completely avoidable. A library will generally set one global which will act as a &amp;lsquo;namespace&amp;rsquo; for their entire app. For example, jQuery sets two globals &lt;code&gt;jQuery&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; and all their methods are available through those two globals so unless you&amp;rsquo;re trying to use &lt;code&gt;jQuery&lt;/code&gt; or &lt;code&gt;$&lt;/code&gt; as your own namespace then you shouldn&amp;rsquo;t notice any conflicts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most companies name their global namespace after their company: &lt;code&gt;var mycompany_app = /* code */;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;types&#34;&gt;Types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;JavaScript types are split into two groups: &lt;code&gt;primitive&lt;/code&gt; types and &lt;code&gt;reference&lt;/code&gt; types.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Numbers&lt;/code&gt;, &lt;code&gt;Booleans&lt;/code&gt;, &lt;code&gt;Strings&lt;/code&gt;, &lt;code&gt;Null&lt;/code&gt; and &lt;code&gt;Undefined&lt;/code&gt; types are primitive.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Objects&lt;/code&gt;, &lt;code&gt;Arrays&lt;/code&gt;, and &lt;code&gt;Functions&lt;/code&gt; are reference types.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&amp;rsquo;s important to know the different types because at some point in your JavaScript code you&amp;rsquo;ll want to pass around values and objects and you might notice some issues with doing so. For example, you&amp;rsquo;ll notice that JavaScript passes &lt;code&gt;Objects&lt;/code&gt;/&lt;code&gt;Arrays&lt;/code&gt;/&lt;code&gt;Functions&lt;/code&gt; by reference, and passes primitives such as &lt;code&gt;Booleans&lt;/code&gt;/&lt;code&gt;Strings&lt;/code&gt;/&lt;code&gt;Numbers&lt;/code&gt;/&lt;code&gt;Null&lt;/code&gt;/&lt;code&gt;Undefined&lt;/code&gt; by value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What this means is if you have an Array and want to copy it so you can make changes to the copy (e.g. you want to leave the original as it is) then you might think to do something like this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var my_arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];&#xA;var new_arr = my_arr;&#xA;&#xA;new_arr.push(&#39;d&#39;);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…you might think that &lt;code&gt;new_arr&lt;/code&gt; will be &lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;]&lt;/code&gt; and &lt;code&gt;my_arr&lt;/code&gt; would still be equal to &lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]&lt;/code&gt; but you&amp;rsquo;d be wrong because Arrays are passed by &amp;lsquo;reference&amp;rsquo; and so your change: &lt;code&gt;new_arr.push(&#39;d&#39;);&lt;/code&gt; is effectively doing this: &lt;code&gt;my_arr.push(&#39;d&#39;);&lt;/code&gt;, hence &lt;code&gt;my_arr&lt;/code&gt; now has the value of &lt;code&gt;[&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;]&lt;/code&gt; and so does &lt;code&gt;new_arr&lt;/code&gt; because it really is just referencing (i.e. pointing to) &lt;code&gt;my_arr&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So be careful.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;objects&#34;&gt;Objects&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To create a new &lt;code&gt;Object&lt;/code&gt; use the syntax: &lt;code&gt;{}&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = {&#xA;    name: &#39;Mark&#39;,&#xA;    location: &#39;London, England&#39;&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;A variable added to an Object is known as a &amp;lsquo;property&amp;rsquo;.&lt;br&gt;&#xA;A function added to an Object is known as a &amp;lsquo;method&amp;rsquo;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;…this naming convention originates from traditional Object-Oriented languages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So for example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = {&#xA;    /* Property */&#xA;        name: &#39;Mark&#39;,&#xA;    /* Property */&#xA;        location: &#39;London, England&#39;,&#xA;    /* Method */&#xA;        get_details: function(){&#xA;            return this.name + &#39; is from &#39; + this.location; // =&amp;gt; &amp;quot;Mark is from London, England&amp;quot;&#xA;        }&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;nearly-everything-in-javascript-is-an-object&#34;&gt;(Nearly)Everything in JavaScript is an Object&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;One thing to be clear on is that nearly everything in JavaScript is an object (e.g. Functions, Arrays, Numbers, Strings etc). They all inherit their properties/attributes from the top level Object, and this is made possible in JavaScript via what&amp;rsquo;s called the &amp;lsquo;prototype chain&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We won&amp;rsquo;t go into the &amp;lsquo;prototype&amp;rsquo; too deeply now but the following section will touch on how it works briefly.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;prototype&#34;&gt;Prototype&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Every Object you create in JavaScript has a hidden object tied to it. This hidden object is called the &amp;lsquo;prototype&amp;rsquo; for that object, and what this means is that your object you&amp;rsquo;ve created will inherit properties from the prototype.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All &amp;lsquo;objects&amp;rsquo; that you create (e.g. &lt;code&gt;var obj = {};&lt;/code&gt;) have the same prototype object they point to/reference - which is the top level &lt;code&gt;Object&lt;/code&gt; in JavaScript. We call this &lt;code&gt;Object.prototype&lt;/code&gt;, and this top level &lt;code&gt;Object&lt;/code&gt; itself has no prototype (it&amp;rsquo;s the only object that has no prototype because nothing precedes it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All built-in Constructors (e.g. &lt;code&gt;Array.prototype&lt;/code&gt;, &lt;code&gt;Date.prototype&lt;/code&gt;) inherit from the &lt;code&gt;Object.prototype&lt;/code&gt; and this linked set of objects is known as the &amp;lsquo;prototype chain&amp;rsquo; and is how &amp;lsquo;inheritance&amp;rsquo; works (see below for a short mention of inheritance and other forms of code reuse).&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;accessing-properties-methods&#34;&gt;Accessing properties/methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To access properties/methods you can use either the dot notation or the bracket notation. The difference is in whether the property/method name is known at the type of execution or not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the previous example code, if your program was written by you then to access the &amp;lsquo;name&amp;rsquo; property you would simply use: &lt;code&gt;obj.name&lt;/code&gt; - but if your application accepted input from the user (where by you asked them what property/method they wanted to access) you obviously don&amp;rsquo;t know before hand what the user is going to choose. In this instance you would use the bracket notation:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var user_input = document.getElementById(&#39;my_form_input&#39;);&#xA;console.log(obj[user_input]);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The other time you&amp;rsquo;ll need to use bracket notation is if you want to access a property that has special characters:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = { &#xA;    &#39;my property&#39;: 123 // YOU SHOULD NEVER NEED TO CREATE A PROPERTY NAME LIKE THIS&#xA;};&#xA;&#xA;console.log(obj[&#39;my property&#39;]);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So the majority of the time you&amp;rsquo;ll just use the dot notation, but depending on the dynamic aspect of your program you may need to use bracket notation every once in a while.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;class-attribute&#34;&gt;Class Attribute&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Every object has a &lt;em&gt;class&lt;/em&gt; attribute which provides information about the object&amp;rsquo;s type.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sounds pretty useful, but unfortunately neither of the current specifications (ES3 or ES5) allow you to access this attribute!?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But there is a trick to accessing an object&amp;rsquo;s &lt;em&gt;class&lt;/em&gt; attribute and that is to call the &lt;code&gt;toString()&lt;/code&gt; method on the top level &lt;code&gt;Object.prototype&lt;/code&gt; but using it on the relevant object you want to get the class of. The following example demonstrates the most common use case of accessing the &lt;em&gt;class&lt;/em&gt; attribute: trying to work out if an object is actually an &lt;code&gt;Array&lt;/code&gt;…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var arr = [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;];&#xA;&#xA;// =&amp;gt; &amp;quot;object&amp;quot; - well that&#39;s not right&#xA;// it should return the type as &#39;Array&#39;! (note: this is a known JavaScript bug)&#xA;console.log(typeof arr); &#xA;&#xA;console.log(Object.prototype.toString.call(arr)); // =&amp;gt; &amp;quot;[object Array]&amp;quot; - that&#39;s more like it&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…what we&amp;rsquo;ve done here is used a method available to all &lt;code&gt;Function&lt;/code&gt;&amp;rsquo;s called &lt;code&gt;.call()&lt;/code&gt;. What this method does is let you call another function (i.e. borrow a function) but use the calling context as the &lt;code&gt;this&lt;/code&gt; value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That previous sentence probably didn&amp;rsquo;t make a lot of sense because we&amp;rsquo;ve not covered &lt;code&gt;this&lt;/code&gt; or anything to do with contexts/execution environments etc - but try and stick with it for a moment and understand that what we&amp;rsquo;ve done is called the &lt;code&gt;Object.prototype&lt;/code&gt;&amp;rsquo;s &lt;code&gt;toString&lt;/code&gt; method but we&amp;rsquo;ve called it as if it was our Array that had executed &lt;code&gt;toString&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way this trick works actually requires a deep level understanding of how JavaScript handles its conversion of data types: something I definitely wont go into here).&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;arrays&#34;&gt;Arrays&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Arrays are like a simplified Object.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An Object is effectively a mapping of names (identifiers) to values…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = {&#xA;    name: value,&#xA;    name: value,&#xA;    name: value&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…an Array is the same with the exception that the &amp;lsquo;name&amp;rsquo; identifiers are automatically incremented numerical values. So an Array like this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var arr = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…would effectively be similar to the following object…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = {&#xA;    0: &#39;a&#39;,&#xA;    1: &#39;b&#39;,&#xA;    2: &#39;c&#39;&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: the above object with numerical keys requires you to use the bracket notation to access the identifiers (e.g. &lt;code&gt;obj[0]&lt;/code&gt;) as &lt;code&gt;obj.0&lt;/code&gt; would result in a &lt;code&gt;SyntaxError: Unexpected number&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;methods&#34;&gt;Methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Arrays come with many methods (functions) that let you manipulate and filter the data contained within the Array.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some methods change the data in the Array (&lt;em&gt;mutators&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some methods return a new Array with the data changed (&lt;em&gt;accessors&lt;/em&gt; - not the best/most descriptive name really,  as it suggests these methods just &amp;lsquo;access&amp;rsquo; data when that&amp;rsquo;s not always the case).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some methods loop through the data (&lt;em&gt;iterators&lt;/em&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Below are some examples of each…&lt;/p&gt;&#xA;&#xA;&lt;table&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;th&gt;Mutators&lt;/th&gt;&#xA;        &lt;th&gt;Accessors&lt;/th&gt;&#xA;        &lt;th&gt;Iterators&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/pop&#34;&gt;pop&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/concat&#34;&gt;concat&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter&#34;&gt;filter&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/push&#34;&gt;push&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/join&#34;&gt;join&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach&#34;&gt;forEach&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/reverse&#34;&gt;reverse&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice&#34;&gt;slice&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/every&#34;&gt;every&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/shift&#34;&gt;shift&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf&#34;&gt;indexOf&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map&#34;&gt;map&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort&#34;&gt;sort&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/lastIndexOf&#34;&gt;lastIndexOf&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some&#34;&gt;some&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/splice&#34;&gt;splice&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;&#34;&gt;&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce&#34;&gt;reduce&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/unshift&#34;&gt;unshift&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;&#34;&gt;&lt;/a&gt;&lt;/td&gt;&#xA;        &lt;td&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/ReduceRight&#34;&gt;reduceRight&lt;/a&gt;&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 id=&#34;conditional-statements&#34;&gt;Conditional Statements&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Conditional statements are &amp;lsquo;control logic&amp;rsquo;. This means that depending on the result of a specified condition the corresponding branch of logic will be executed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a few different conditional statements such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;if&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ternary&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The simplest way to understand them is to see the syntax.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;if-statement&#34;&gt;If Statement&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (condition) {&#xA;&#xA;    // if &#39;condition&#39; evaluated to true then run this code&#xA;    &#xA;} else if (other_condition) {&#xA;    &#xA;    // if &#39;other_condition&#39; evaluated to true then run this code&#xA;    &#xA;} else {&#xA;    &#xA;    // other wise we&#39;ll run this code as a fallback&#xA;    &#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So a basic example would be something like this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var can_drink = false;&#xA;var age = 18;&#xA;&#xA;if (age &amp;gt;= 18) {&#xA;    can_drink = true;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;switch-statement&#34;&gt;Switch Statement&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you have lots of checks against the same variable/condition then you&amp;rsquo;re better off using a &lt;code&gt;switch&lt;/code&gt; statement…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;switch (condition) {&#xA;    case x:&#xA;        // Execute this code block&#xA;        break;&#xA;    case y:&#xA;        // Execute this code block&#xA;        break;&#xA;    case z:&#xA;        // Execute this code block&#xA;        break;&#xA;    default:&#xA;        // Execute this code block&#xA;        break;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;An example of using this statement would be…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var car = &#39;Porsche&#39;;&#xA;&#xA;switch (car) {&#xA;    case &#39;Ford&#39;:&#xA;        // Execute this code block if car is &#39;Ford&#39;&#xA;        break;&#xA;    case &#39;Porsche&#39;:&#xA;        // Execute this code block if car is &#39;Porsche&#39;&#xA;        break;&#xA;    case &#39;BMW&#39;:&#xA;        // Execute this code block if car is &#39;BMW&#39;&#xA;        break;&#xA;    default:&#xA;        // Execute this code block if car is none of the above&#xA;        break;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;ternary-statement&#34;&gt;Ternary Statement&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;For very short &lt;code&gt;if&lt;/code&gt; statements you can also use a shortened syntax (a conditional operator sometimes referred to as a &amp;lsquo;ternary&amp;rsquo; operator because of its three operands). The syntax is like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;condition ? true : false&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…and can be used like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var age = 18;&#xA;var can_drink = (age &amp;gt;= 18) ? true : false; // can_drink will equal a Boolean value of true&#xA;&#xA;var x = &#39;abc&#39;;&#xA;var y = (x === &#39;abc&#39;) ? &#39;def&#39; : &#39;xyz&#39;; // y will equal a String value of &#39;def&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;coercion&#34;&gt;Coercion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One of the areas of most confusion in JavaScript is its ability to coerce data &amp;lsquo;types&amp;rsquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The best thing to do is to just try and take advantage of JavaScript&amp;rsquo;s ability to coerce objects into different types and use it to your advantage to make your code more succinct.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, with an &lt;code&gt;if&lt;/code&gt; conditional statement JavaScript will try to coerce the expression into either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var element = document.getElementById(&#39;js-element&#39;);&#xA;&#xA;if (element) {&#xA;    // if the DOM element is available then this conditional&#xA;    // will coerce `element` into a Boolean value of true &#xA;    // and hence the condition will pass.&#xA;    &#xA;    // If the DOM element doesn&#39;t exist then the resulting value will be null&#xA;    // and null is converted into a Boolean value of false &#xA;    // and hence the condition will not pass&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In the above example JavaScript automatically converts the condition into a Boolean, but you can manually coerce a value into a Boolean by using the double negation operator &lt;code&gt;!!&lt;/code&gt; like so&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj = { age: 0, year: 1980 };&#xA;&#xA;!!obj.age // =&amp;gt; false (because zero coerces to false)&#xA;!!obj.year // =&amp;gt; true (any number greater than zero coerces to true)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You can also use a single negation operator &lt;code&gt;!&lt;/code&gt; to return the opposite Boolean value of an object (this is useful for saying &amp;lsquo;if NOT x&amp;rsquo;)…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var bool = false;&#xA;&#xA;if (!bool) {&#xA;    // this statement is executed if &#39;bool&#39; is NOT true (i.e. if it&#39;s false)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;some-quick-notes&#34;&gt;Some quick notes:&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;All Objects/Arrays coerce to true (even an empty Array).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An empty String wil coerce to false.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is a lot to learn about JavaScript&amp;rsquo;s coercion process, so for full details please see the following article: &lt;a href=&#34;http://webreflection.blogspot.co.uk/2010/10/javascript-coercion-demystified.html&#34; target=&#34;_blank&#34;&gt;http://webreflection.blogspot.co.uk/2010/10/javascript-coercion-demystified.html&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Functions make it easier to create re-useable code. They are simply blocks of JavaScript code that can be called/executed multiple times.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An example of the function syntax is as follows…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function identifier (parameters) {&#xA;    // statements&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…which could be used like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function add (a, b) {&#xA;    return a + b;&#xA;}&#xA;&#xA;console.log(add(1, 1)); // =&amp;gt; 2&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;parameters&#34;&gt;Parameters&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Functions accept any number of &amp;lsquo;parameters&amp;rsquo; (also known as &amp;lsquo;arguments&amp;rsquo;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Within a function you can access all arguments via a special &lt;code&gt;arguments&lt;/code&gt; property…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function test (a, b, c) { &#xA;    console.log(arguments); &#xA;}&#xA;&#xA;test(1, 2, 3) // =&amp;gt; [1, 2, 3]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…you&amp;rsquo;ll notice in the above example it looks like the &lt;code&gt;arguments&lt;/code&gt; property is an Array but it&amp;rsquo;s not. It&amp;rsquo;s an &amp;lsquo;array-like&amp;rsquo; object. So you can access the keys values much like an Array but you don&amp;rsquo;t have access to the Array methods.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;return-values&#34;&gt;Return values&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If a function doesn&amp;rsquo;t explicitly return a value (if you look at our &lt;code&gt;add&lt;/code&gt; function example above you&amp;rsquo;ll see we explicitly returned &lt;code&gt;a + b&lt;/code&gt;) then the function will have a return value of &lt;code&gt;undefined&lt;/code&gt;. Hence when you run certain code snippets in a browsers web console you&amp;rsquo;ll normally see &lt;code&gt;undefined&lt;/code&gt; appear directly underneath the code you&amp;rsquo;ve just written.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;borrowing-methods&#34;&gt;Borrowing methods&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Objects have two core methods made available to them: &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These two methods are the same (i.e. they do the same thing - which is to call a function &lt;em&gt;indirectly&lt;/em&gt; while specifying a value for &lt;code&gt;this&lt;/code&gt;) but with one small difference: &lt;code&gt;call&lt;/code&gt; requires you pass through any arguments for the function as a comma separated list while &lt;code&gt;apply&lt;/code&gt; requires you pass through any arguments for the function as an Array of values.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The purpose of these methods is to allow you to &lt;em&gt;borrow&lt;/em&gt; a function/method from another object. The following code demonstrates its usage and how powerful it can be…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var obj1 = {&#xA;    name: &#39;Bob&#39;&#xA;};&#xA;&#xA;var obj2 = { &#xA;    name: &#39;Mark&#39;, &#xA;    speak: function(){ &#xA;        return &#39;My name is &#39; + this.name;&#xA;    } &#xA;}&#xA;&#xA;obj2.speak(); // =&amp;gt; &#39;My name is Mark&#39;&#xA;&#xA;// obj1 doesn&#39;t have a speak method and we don&#39;t want to add extra code to that&#xA;// object when &#xA;// obj2 already has the same method already defined. We want to be able to just&#xA;// borrow obj2&#39;s &#39;speak&#39; method!&#xA;&#xA;obj2.speak.call(obj1); // =&amp;gt; &#39;My name is Bob&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;…you can see how by using the &lt;code&gt;call&lt;/code&gt; method we can make better use of existing functions and so we become more productive as well as have smaller and more efficient code.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;code-reuse-inheritance&#34;&gt;Code Reuse (inheritance)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The final subject I want to briefly cover is &amp;lsquo;code reuse&amp;rsquo;. In most object-oriented programming languages the main principle of code reuse is done via &lt;em&gt;inheritance&lt;/em&gt; (this is where you have a base object that all other objects inherit properties/methods from - much like how JavaScript already works! i.e. all objects inherit properties/methods from the top level &lt;code&gt;Object.prototype&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way you implement inheritance is by taking advantage of the &lt;code&gt;prototype&lt;/code&gt; chain in JavaScript.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are multiple ways to use the prototype chain, one populate way is to try and emulate the &amp;lsquo;Classical Inheritance&amp;rsquo; style syntax (i.e. most programming languages have a &lt;code&gt;Class&lt;/code&gt; keyword that makes creating objects based off a blueprint Class very easy but JavaScript doesn&amp;rsquo;t have the concept of Class&amp;rsquo;es - not yet any way).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An example of how to emulate Class style syntax in JavaScript (currently) is by using functions as &amp;lsquo;Constructors&amp;rsquo; like so…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var Person = function (settings) {&#xA;   // Instance properties (any new instances of the Person class will have these properties)&#xA;   this.name = settings.name || &#39;no name given&#39;;&#xA;   this.age = settings.age || &#39;no age given&#39;;&#xA;&#xA;   // Instance method (any new instances of the Person class will have this method)&#xA;   this.getName = function() {&#xA;      return this.name;&#xA;   };&#xA;};&#xA;&#xA;// Create a new instance of the Person Class&#xA;var bob = new Person({ name:&#39;Bob&#39;, age:7 });&#xA;&#xA;// Add a method to this instance of the Person Class only (no other instances&#xA;// created will have this method)&#xA;bob.getAge = function() {&#xA;   return this.age;&#xA;}&#xA;&#xA;// Test the bob instance has access to both methods&#xA;bob.getName();&#xA;bob.getAge();&#xA;&#xA;// Create another instance of the Person Class&#xA;var user = new Person({ name:&#39;Mark&#39; });&#xA;&#xA;// Notice the user has access to a &#39;getName&#39; method but not a &#39;getAge&#39; method&#xA;user.getName();&#xA;&#xA;// I know this will error so I&#39;m wrapping it in a try statement&#xA;try {&#xA;   user.getAge();&#xA;} catch(err) {&#xA;   alert(err); // Uncaught TypeError: Object [object Object] has no method &#39;getAge&#39;&#xA;}&#xA;&#xA;// Add a method to the Person Class&#39; prototype chain &#xA;// all instances of the Person Class will now get this method&#xA;// even those already defined&#xA;Person.prototype.getNameAndAge = function() {&#xA;   return &#39;Hi, my name is &#39; + this.name + &#39;, and I\&#39;m &#39; + this.age + &#39; years old.&#39;;&#xA;}&#xA;&#xA;// Test this new method is accessible to all instances of the Person Class&#xA;bob.getNameAndAge();&#xA;user.getNameAndAge();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;composition&#34;&gt;Composition&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is another code reuse pattern you can use instead of &amp;lsquo;inheritance&amp;rsquo; called &amp;lsquo;composition&amp;rsquo;. The way it works is instead of inheriting methods/properties from a blueprint/base object you instead borrow the methods using &lt;code&gt;call&lt;/code&gt; or &lt;code&gt;apply&lt;/code&gt; (as we&amp;rsquo;ve seen previously).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An example of this is as follows…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var person = {&#xA;        names: [&#39;James&#39;, &#39;Neil&#39;, &#39;Russ&#39;, &#39;Stuart&#39;]&#xA;    };&#xA;&#xA;var people = {&#xA;    names: [&#39;Ash&#39;, &#39;Brad&#39;, &#39;Mark&#39;, &#39;Mike&#39;],&#xA;    speak: function(which) {&#xA;        return &#39;Hi, my name is &#39; + this.names[which];&#xA;    }&#xA;};&#xA;&#xA;// Composition not Inheritance&#xA;people.speak.call(person, 1); // =&amp;gt; &#39;Hi, my name is Neil&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3 id=&#34;mixins&#34;&gt;Mixins&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Another code reuse pattern is called a &amp;lsquo;mixin&amp;rsquo; - which instead of using &amp;lsquo;inheritance&amp;rsquo; we simply copy over the functions/properties we want to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The following example demonstrates how this works…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function extend(destination, source, overwrite) {&#xA;    var overwrite = overwrite || false;&#xA;    for (var i in source) {&#xA;        if (source.hasOwnProperty(i)) {&#xA;            // If we&#39;re not allowed to overwrite an existing property… &#xA;            if (!overwrite) {&#xA;                // …then we check to see if the property is undefined… &#xA;                if (destination[i] === undefined) {&#xA;                    // …if it is then we know we can copy the property to the destination object&#xA;                    destination[i] = source[i];&#xA;                }&#xA;            } else {&#xA;                destination[i] = source[i];&#xA;            }&#xA;        }&#xA;    }&#xA;    return destination; &#xA;}&#xA;&#xA;var person = {&#xA;        names: [&#39;James&#39;, &#39;Neil&#39;, &#39;Russ&#39;, &#39;Stuart&#39;]&#xA;    };&#xA;&#xA;var people = {&#xA;    names: [&#39;Ash&#39;, &#39;Brad&#39;, &#39;Mark&#39;, &#39;Mike&#39;],&#xA;    speak: function(which) {&#xA;        return &#39;Hi, my name is &#39; + this.names[which];&#xA;    }&#xA;};&#xA;&#xA;extend(person, people); // copy properties from `people` to `person`&#xA;&#xA;// `person` now has a `speak` method it didn&#39;t have originally &#xA;person.speak(1); // =&amp;gt; &#39;Hi, my name is Neil&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;OK, this has been a super brief/quick run through of different JavaScript concepts and language features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This isn&amp;rsquo;t supposed to be even remotely an exhaustive discussion - have you seen the size of &amp;lsquo;JavaScript: The Definitive Guide&amp;rsquo; !?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Hopefully this has at least been enough to get you started and interested in learning more. If there are any issues or errors then please get in contact and let me know.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/javascript-101/</guid>
      <link>https://www.integralist.co.uk/posts/javascript-101/</link>
      <pubDate>Fri, 02 Nov 2012 00:00:00 +0000</pubDate>
      <title>JavaScript 101</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a super quick post to introduce you to a method of writing more maintainable CSS by using what&amp;rsquo;s called &amp;ldquo;&lt;a href=&#34;http://bem.info&#34; target=&#34;_blank&#34;&gt;BEM&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Update: &lt;a href=&#34;http://twitter.com/necolas&#34; target=&#34;_blank&#34;&gt;@necolas&lt;/a&gt; made a comment worth noting, that I&amp;rsquo;m using a modified version of the BEM naming conventions (BEM is a total framework that goes beyond just naming of classes and writing maintainable CSS). So I thought it best to make note of that here so as to not cause any confusion.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;bem-block-element-modifier&#34;&gt;BEM: Block, Element, Modifier&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;BEM stands for &amp;ldquo;Block, Element, Modifier&amp;rdquo; and is a simple but effective way to group together different components/widgets (as shown by the following visual aid).&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;delayed-image-load&#34; data-src=&#34;/images/generated/BEM-1024.png&#34; data-width=&#34;1024&#34;&gt;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;Within each defined &amp;lsquo;Block&amp;rsquo; you can have multiple &amp;lsquo;elements&amp;rsquo; that make up the object, and for each element (depending on where it appears within the block) you might need to &amp;lsquo;modify&amp;rsquo; the state of the element.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The principles are similar to other methods of structuring CSS (&lt;a href=&#34;https://github.com/stubbornella/oocss/wiki&#34; target=&#34;_blank&#34;&gt;OOCSS&lt;/a&gt;/&lt;a href=&#34;http://smacss.com&#34; target=&#34;_blank&#34;&gt;SMACSS&lt;/a&gt;) but they are greatly simplified in comparison without giving up any of the architectural benefits.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The best way to understand BEM is to see an example of how it&amp;rsquo;s used (see next section). But if you want the full details of its history and some more detailed/visual break down of the concepts then please see the &lt;a href=&#34;http://bem.info&#34; target=&#34;_blank&#34;&gt;BEM&lt;/a&gt; website.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Below we have a money calculator widget. You enter an amount of money (e.g. £2.12p) and when you press on &amp;lsquo;calculate&amp;rsquo; it&amp;rsquo;ll return to you a list of coins required to make up the amount specified.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The HTML is very simple&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;section&amp;gt;&#xA;    &amp;lt;h1&amp;gt;Sterling Calculator&amp;lt;/h1&amp;gt;&#xA;    &amp;lt;form action=&amp;quot;process.php&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&#xA;        &amp;lt;p&amp;gt;Please enter an amount: (e.g. 92p, &amp;amp;pound;2.12)&amp;lt;/p&amp;gt;&#xA;        &amp;lt;p&amp;gt;&#xA;            &amp;lt;input name=&amp;quot;amount&amp;quot;&amp;gt; &#xA;            &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Calculate&amp;quot;&amp;gt;&#xA;        &amp;lt;/p&amp;gt;&#xA;    &amp;lt;/form&amp;gt;&#xA;&amp;lt;/section&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So lets add in our classes for styling this widget and lets go on to break down what we&amp;rsquo;ve added and why&amp;hellip;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;section class=&amp;quot;widget&amp;quot;&amp;gt;&#xA;    &amp;lt;h1 class=&amp;quot;widget__header&amp;quot;&amp;gt;Sterling Calculator&amp;lt;/h1&amp;gt;&#xA;    &amp;lt;form class=&amp;quot;widget__form&amp;quot; action=&amp;quot;process.php&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&#xA;        &amp;lt;p&amp;gt;Please enter an amount: (e.g. 92p, &amp;amp;pound;2.12)&amp;lt;/p&amp;gt;&#xA;        &amp;lt;p&amp;gt;&#xA;            &amp;lt;input name=&amp;quot;amount&amp;quot; class=&amp;quot;widget__input widget__input--amount&amp;quot;&amp;gt; &#xA;            &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Calculate&amp;quot; class=&amp;quot;widget__input widget__input--submit&amp;quot;&amp;gt;&#xA;        &amp;lt;/p&amp;gt;&#xA;    &amp;lt;/form&amp;gt;&#xA;&amp;lt;/section&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;First thing to notice is that we&amp;rsquo;ve determined the top level &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; element to be our &amp;lsquo;block&amp;rsquo;. This is the top level containing element. We&amp;rsquo;ve added a class of &lt;code&gt;widget&lt;/code&gt; and this will be our namespace for this object/widget (whatever you prefer to call it).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From here on all elements that we added classes to within this &amp;lsquo;block&amp;rsquo; will be namespaced to the top level name of &lt;code&gt;widget&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wanted to style the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element so I added the class &lt;code&gt;widget__form&lt;/code&gt;. The double underscores allow us to easily recognise a class as being part of the &lt;code&gt;widget&lt;/code&gt; block. We see this used on the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements as well: &lt;code&gt;widget__input&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a list of the elements styled…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;widget&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;widget__header&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;widget__form&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;widget__input&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Notice that there are two other classes used: &lt;code&gt;widget__input--amount&lt;/code&gt; and &lt;code&gt;widget__input--submit&lt;/code&gt;. These are our &amp;lsquo;modifiers&amp;rsquo;. They modify the state of our elements.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&amp;rsquo;s look at where these have been used. I&amp;rsquo;ve applied the same class of &lt;code&gt;widget__input&lt;/code&gt; on both &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements (because they both have the same base structure/styling). But both elements do have slight differences in their appearance, hence the use of a &amp;lsquo;modifier&amp;rsquo; to apply the additional unique styles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Modifiers are written with two hyphens(dashes) like so: &lt;code&gt;block__element--modifier&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means that our CSS code for this widget ends up looking like this…&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;.widget {&#xA;    background-color: #FC3;&#xA;}&#xA;&#xA;.widget__header {&#xA;    color: #930;&#xA;    font-size: 3em;&#xA;    margin-bottom: 0.3em;&#xA;    text-shadow: #FFF 1px 1px 2px;&#xA;}&#xA;&#xA;.widget__input {&#xA;    -webkit-border-radius: 5px;&#xA;       -moz-border-radius: 5px;&#xA;         -o-border-radius: 5px;&#xA;            border-radius: 5px;&#xA;&#xA;    font-size: 0.9em;&#xA;    line-height: 1.3;&#xA;    padding: 0.4em 0.7em;&#xA;}&#xA;&#xA;.widget__input--amount {&#xA;    border: 1px solid #930;&#xA;}&#xA;&#xA;.widget__input--submit {&#xA;    background-color: #EEE;&#xA;    border: 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2 id=&#34;why-bem-over-the-others&#34;&gt;Why BEM over the others?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&amp;rsquo;ve tried a lot of different ways of writing CSS over the years. It went something like this…&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;No structure, everything in one file loaded on every page of a site.&lt;/li&gt;&#xA;&lt;li&gt;Separate files to try and keep page specific content together, but still no real structure.&lt;/li&gt;&#xA;&lt;li&gt;Standard &lt;a href=&#34;https://github.com/stubbornella/oocss/wiki&#34; target=&#34;_blank&#34;&gt;OOCSS (Object-Oriented CSS)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://smacss.com&#34; target=&#34;_blank&#34;&gt;SMACSS (Scalable and Modular Architecture for CSS)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;…and now BEM.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The reason I choose BEM over other methodologies comes down to this: it&amp;rsquo;s less confusing than the other methods (i.e. SMACSS) but still provides us the good architecture we want (i.e. OOCSS) and with a recognisable terminology.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me OOCSS isn&amp;rsquo;t strict enough. It let&amp;rsquo;s developers go wild with how they name their objects. But I&amp;rsquo;ve seen that get really messy on larger projects, or projects with more than one developer and because of the lack of strictness in naming conventions developers become confused on what classes are supposed to be doing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With regards to SMACSS: it&amp;rsquo;s almost too strict in the sense that I think it&amp;rsquo;s &lt;em&gt;over structured&lt;/em&gt;. When I first started using it I thought this was the solution I had been searching for but all that ended up happening was that I had so many fragmented areas of CSS that I didn&amp;rsquo;t know where to go first. It was too over whelming.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This might not be the case for some people, but for me these are all instances of the old adage: &amp;ldquo;&lt;em&gt;don&amp;rsquo;t make me think&lt;/em&gt;&amp;rdquo;. If I have to think too hard about how something works, or where I need to find the code for something then (in my opinion) that methodology has failed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;BEM succeeds because it provides a good object oriented structure with a familiar terminology and is simple enough to not get in your way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But like with any tool, it can be misused. In the end it comes down to the overall skill and understanding of the developer.&lt;/p&gt;&#xA;&#xA;&lt;h3 id=&#34;simplicity&#34;&gt;Simplicity&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As I said before, the reason I find BEM a better option is the simplicity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even down to the terminology used is simplified compared to other methodologies. For example, depending on who you talk to about structured CSS you may hear the words:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;objects&lt;/li&gt;&#xA;&lt;li&gt;modules&lt;/li&gt;&#xA;&lt;li&gt;widgets&lt;/li&gt;&#xA;&lt;li&gt;components&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;…notice the terminology is different but what they refer to are effectively the same thing. No wonder it can become confusing to some people.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;BEM is different in that its terminology is based around the environment it works for: HTML and CSS. We all know when working in CSS what a &amp;lsquo;block&amp;rsquo; is, it&amp;rsquo;s the fundamental building block (no pun intended) of how elements on the page are rendered, but that term can also be understood when used like so…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I saw this block of code the other day, it was hideous.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;…you know within the context of that sentence the person speaking is referring to a chunk of code, a grouping of code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The word &amp;lsquo;Block&amp;rsquo; is simple but a very focused term, and more importantly it is a very familiar term.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We also know when working in CSS that ultimately we&amp;rsquo;re targeting &amp;lsquo;elements&amp;rsquo;. No other word better fits the description, because that is exactly what we&amp;rsquo;re doing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And lastly, the word &amp;lsquo;modifier&amp;rsquo; again is a simple but fully understood and familiar term used by developers…&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I want to modify this element, how should I do that?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3 id=&#34;but-still-structured&#34;&gt;But still structured&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;But with this simplified terminology/structure it gives us all the tools we need to write maintainable and easily understandable code. BEM easily scales with the size of a project.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I know I&amp;rsquo;ve said it before about SMACSS (&amp;rdquo;&lt;em&gt;wow, I think this is it!&lt;/em&gt;&amp;rdquo;) but even when I first started using SMACSS I still had niggling feelings about &amp;ldquo;&lt;em&gt;hmm, it&amp;rsquo;s a little complicated getting this all in place, but it seems to work well&lt;/em&gt;&amp;rdquo;. With BEM I&amp;rsquo;ve not had any of those concerns. The only initial concern I had was with the look of it. I didn&amp;rsquo;t like the double underscores or the double dashes. But now I actually like them!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to see more good usage of BEM then I&amp;rsquo;ll refer you to a small CSS abstraction library called &lt;a href=&#34;https://github.com/csswizardry/inuit.css&#34; target=&#34;_blank&#34;&gt;inuit.css&lt;/a&gt; by &lt;a href=&#34;http://csswizardry.com/&#34; target=&#34;_blank&#34;&gt;Harry Roberts&lt;/a&gt; as well as &lt;a href=&#34;https://github.com/Integralist/integralist.github.com&#34; target=&#34;_blank&#34;&gt;my own website&amp;rsquo;s source code&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/maintainable-css-with-bem/</guid>
      <link>https://www.integralist.co.uk/posts/maintainable-css-with-bem/</link>
      <pubDate>Wed, 12 Sep 2012 00:00:00 +0000</pubDate>
      <title>Maintainable CSS with BEM</title>
    </item>
    <item>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This was intended as a short and overly simplified post about Host methods and Native methods.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;what-they-are&#34;&gt;What they are?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Native methods are built-in functions provided by the ECMAScript core specification. So things like Object methods (e.g. &lt;code&gt;Object.create&lt;/code&gt;), Array methods (e.g. &lt;code&gt;Array#forEach&lt;/code&gt;) etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Host methods are functions provided by the host environment (most of the time when working in web development the host environment will be the user’s web browser). So things like the DOM API and the Events object are host objects/methods (e.g. &lt;code&gt;attachEvent&lt;/code&gt; is a host method and &lt;code&gt;addEventListener&lt;/code&gt; is a host method)&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;how-to-detect-them&#34;&gt;How to detect them?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Detecting Native methods is relatively straight forward. The real problem comes when you need to determine whether the object/method you’re detecting actually works the way the specification dictates it should work. So just checking it is available to use isn’t good enough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Detecting host methods is similar but a lot more problematic, because the ECMAScript specification states that the host environment can implement certain methods however they like and so there is no guarantee that your checks for certain host methods (which may work today) will work in future.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We’ll give an example of each so you can get an idea of what I mean…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To detect a Native method such as Array#forEach you should be able to do the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if (!Array.prototype.forEach) { &#xA;    /* polyfill for missing forEach method */ &#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Note: polyfill is a term that Remy Sharp coined which means ‘a shim that mimics a future API’ (see: &lt;a href=&#34;http://remysharp.com/2010/10/08/what-is-a-polyfill/&#34; target=&#34;_blank&#34;&gt;http://remysharp.com/2010/10/08/what-is-a-polyfill/&lt;/a&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But the issue you could encounter in this example is if you’re inheriting a project from another developer and they have already extended the Native Array object with a forEach method and their polyfill version of the missing forEach function doesn’t work how the specification has dictated it should then you could find your code errors at hard to debug stages because of the difference in implementation where you’re passing parameters into a polyfill’ed method and that method hasn’t been implemented properly so the extra parameters either throw an error or (potentially worse) silently fail.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where you either ‘suck it and see’ (which is a bad idea, but not always unavoidable), or you attempt genuine ‘feature detection’ which means (in this example) you create a test Array and test the forEach method works how you expect it to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The downsides to this approach (although it is the most robust and future-proof way of writing your code) is that all these checks are a performance penalty. If you’re sure the method you’re checking for is going to work how you expect it to then should you waste time/effort writing additional checks/tests to ensure the method works how the specification dictates? What happens if you do the full feature detection and discover the method doesn’t work how you expect it? You’ll still then need to implement some kind of fallback or lose the functionality that relies on that method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These are important decisions that need to be made and ones that are outside the realms of this post I’m afraid (simply because there are no easy answers).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now, detecting Host methods is actually worse because they can be implemented in any fashion the host environment chooses.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So far it has been &lt;em&gt;noted&lt;/em&gt; that checking the &lt;code&gt;typeof&lt;/code&gt; result for a Host method will normally result in either function, object or unknown, so if you get one of these back as a result then it’s a good chance the host object you’re checking for is available to use, but as you should be able to tell by now, this is a flawed process… fun heh!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, this isn’t a reliable assumption to make, because in a future/new host environment they might have a &lt;code&gt;typeof&lt;/code&gt; result that is none of the above. Literally you could check the &lt;code&gt;typeof&lt;/code&gt; for a method and its result could be &lt;em&gt;spacecraft&lt;/em&gt; - there are no rules as far as the Host environment is concerned!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But for testing a host method exists, the following function has become the de-facto standard:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/*&#xA; * Feature Testing a Host Method&#xA; * Because a callable host object can legitimately have any typeof result then it can&#39;t be relied upon.&#xA; *&#xA; * @notes:&#xA; * The reason for the &amp;amp;&amp;amp; !!object[property] is because in ECMAScript version 3, &#xA; * a null object has typeof result &#39;object&#39; (which is considered a bug).&#xA; * In future versions (ECMAScript 6+) the typeof result will be &#39;null&#39; (as it should be).&#xA; * &#xA; * @reference: http://michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting&#xA; */&#xA;&#xA;function isHostMethod(object, property) {&#xA;    var type = typeof object[property];&#xA;&#xA;    // This is the result we&#39;re expecting (as the test is for a method)&#xA;    return type == &#39;function&#39; || &#xA;           // Protect against ES3 &#39;null&#39; typeof result being &#39;object&#39;&#xA;           (type == &#39;object&#39; &amp;amp;&amp;amp; !!object[property]) || &#xA;           // For IE &amp;lt; 9 when Microsoft used ActiveX objects for Native Functions &#xA;           // (we&#39;re checking property of ActiveX object)&#xA;           type == &#39;unknown&#39;; &#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;So lets take a quick re-cap of what’s going on here:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;function&lt;/code&gt;:&lt;br&gt;&#xA;For most browsers the &lt;code&gt;typeof&lt;/code&gt; operator will result with &lt;code&gt;function&lt;/code&gt; when passed a callable host object&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;&lt;code&gt;&#39;object’ &amp;amp;&amp;amp; !!object[property]&lt;/code&gt;:&lt;br&gt;&#xA;Because we&amp;rsquo;re dealing with host objects we can&amp;rsquo;t expect &lt;code&gt;function&lt;/code&gt; to be returned, and in most cases (as far as ECMAScript 3 [ES3] implementations are concerned) the result will normally be &lt;code&gt;object&lt;/code&gt; which is incorrect but allowed as far as the ES3 spec is concerned.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So first of all we check for &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If that matches we then check to make sure the property coerces to true. The reason for this is that ES3 allows the host to return whatever they like, so if the property you&amp;rsquo;re checking for is actually &lt;code&gt;null&lt;/code&gt; the ES3 &lt;code&gt;typeof&lt;/code&gt; result (for most browsers) will still be &lt;code&gt;object&lt;/code&gt; even though the result is &lt;code&gt;null&lt;/code&gt;! So to work around this issue we coerce the result into a boolean (so if &lt;code&gt;null&lt;/code&gt; is the result it will coerce to false and thus this whole expression will return false, otherwise it&amp;rsquo;ll return true).&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;unknown&lt;/code&gt;:&lt;br&gt;&#xA;In older versions of IE (less than 9) it implements some of its host objects not as Native functions but as ActiveX objects (admittedly this is deep browser implementation talk and normally you don’t need to know this stuff, but in this instance it’s important to understand what the heck is going on with IE).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So, in IE calling the &lt;code&gt;typeof&lt;/code&gt; operator with properties of an ActiveX Object will result in &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2 id=&#34;when-is-it-ok-to-modify-them&#34;&gt;When is it OK to modify them?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Modifying built-in Native objects isn’t as dangerous as host objects (as already noted by Kangax &lt;a href=&#34;http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/&#34; target=&#34;_blank&#34;&gt;http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/&lt;/a&gt;) but care needs to be taken to ensure the augmented object works as the spec dictates (something that isn’t possible all the time, for example like with &lt;code&gt;Object.create&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As far as host objects are concerned, never ever ever ever modify or augment them, just too dangerous.&lt;/p&gt;&#xA;</description>
      <guid>https://www.integralist.co.uk/posts/host-methods-vs-native-methods/</guid>
      <link>https://www.integralist.co.uk/posts/host-methods-vs-native-methods/</link>
      <pubDate>Sun, 22 Apr 2012 00:00:00 +0000</pubDate>
      <title>Host Methods vs Native Methods</title>
    </item>
    <link>https://www.integralist.co.uk/</link>
    <title>integralist</title>
  </channel>
</rss>
