<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Chris Zetter]]></title>
  <link href="http://chriszetter.com/atom.xml" rel="self"/>
  <link href="http://chriszetter.com/"/>
  <updated>2025-07-28T14:02:24+00:00</updated>
  <id>http://chriszetter.com/</id>
  <author>
    <name><![CDATA[Chris Zetter]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[What makes SQL special]]></title>
    
      <link href="https://technicaldeft.com/posts/what-makes-sql-special"/>
    
    <updated>2025-07-20T20:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/07/20/what-makes-sql-special</id>
    <content type="html"><![CDATA[]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[rgSQL: A test suite for database engines]]></title>
    
      <link href="https://technicaldeft.com/posts/rgsql-a-test-suite-for-database-engines"/>
    
    <updated>2025-06-16T20:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/06/16/rgsql-a-test-suite-for-database-engines</id>
    <content type="html"><![CDATA[]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Feedback wanted and the sample solution]]></title>
    
      <link href="http://chriszetter.com/blog/2025/04/08/booknotes-feedback_wanted_and_the_sample_solution/"/>
    
    <updated>2025-04-08T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/04/08/booknotes-feedback_wanted_and_the_sample_solution</id>
    <content type="html"><![CDATA[<p>Booknotes 7.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="feedback-wanted">Feedback wanted</h3>

<p>I’m giving a small number of people access to the guide in exchange for their feedback. If you would like to read the first few chapters and start your implementation <a href="https://technicaldeft.com/contact">send me a message</a>.</p>

<h3 id="a-book-in-two-parts">A book in two parts</h3>

<p>In the interest of releasing early, I’ve split up my original plan for the guide into two parts.  The first part is called ‘<strong>Running SQL</strong>’ and it’s focused on how to parse and execute SQL statements as well as going through database concepts along the way.</p>

<p>I’ve called the second part ‘<strong>Speed and Safety</strong>’ and it’s more focused on a few database concepts that help make queries faster (indexes and concurrent execution) and keep data safe (persistence, transactions).</p>

<p>I’ve made sure that the first part stands on its own. If I complete the second part it will be a free addition to anyone who has the guide.</p>

<h3 id="browsing-the-sample-solution">Browsing the sample solution</h3>

<p>The guide comes with a sample solution in Ruby and I wanted to be able to link to the commits and diffs associated with each chapter. To do this I pushed the solution to GitHub and created branches for every chapter. This means I can link to the <a href="https://github.com/technicaldeft/rgsql-ruby-sample-solution/tree/chapter-2">state of the sample solution after a specific chapter</a> and show <a href="https://github.com/technicaldeft/rgsql-ruby-sample-solution/compare/chapter-1...chapter-2">diffs for all the code added in a chapter</a>.</p>

<p>I wanted a way to update all the branches if I had to change an earlier commit. I wrote a Ruby script to help with this that I can run after rebasing the main branch.</p>

<p>The script has a list of commit messages and corresponding chapter names. For each chapter, it finds what should be the last commit on the branch for that chapter. It then resets the branch for that chapter to that commit. Here’s the part that finds the commit and resets the branch:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">hash</span> <span class="o">=</span> <span class="sb">`git log --grep="^</span><span class="si">#{</span><span class="n">message</span><span class="si">}</span><span class="sb">" --format="%H" -n 1`</span><span class="p">.</span><span class="nf">strip</span>
<span class="sb">`git checkout </span><span class="si">#{</span><span class="n">chapter_name</span><span class="si">}</span><span class="sb">`</span>
<span class="sb">`git reset --hard </span><span class="si">#{</span><span class="nb">hash</span><span class="si">}</span><span class="sb">`</span>
</code></pre></div></div>

<p>I did wonder if GitHub was the best tool to use. I looked at other git solutions that I could host myself (including <a href="https://gogs.io">Gogs</a>, <a href="https://about.gitlab.com/install/">GitLab</a>, <a href="https://about.gitea.com">Gitea</a>, <a href="https://git.zx2c4.com/cgit/">cgit</a> and <a href="https://codemadness.org/stagit.html">Stagit</a>) but didn’t find one that had an interface that was as easy to navigate as GitHub and was worth the complexity in setting it up.</p>

<h3 id="next">Next</h3>

<p>There’s a few bits in the first part of the guide that need to be finished and I’ll be making changes based on any feedback.</p>

<p>This might be may last booknotes. When the guide is available to buy I’m going to focus on ways of promoting it that will better show off its contents. I have ideas for a few articles based on topics in the guide that I could write.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Grouping and my favourite HYTRADBOI talks]]></title>
    
      <link href="http://chriszetter.com/blog/2025/03/01/booknotes-finishing-implementation-and-hytradboi/"/>
    
    <updated>2025-03-01T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/03/01/booknotes-finishing-implementation-and-hytradboi</id>
    <content type="html"><![CDATA[<p>Booknotes 6.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="progress">Progress</h3>
<p>This week I’ve hit the milestone of having a complete sample implementation!</p>

<h3 id="grouping-and-aggregation">Grouping and aggregation</h3>

<p>Grouping and aggregation were the most complex parts to implement. This complexity comes from how grouping changes the structure of the data it acts on and how that interacts with type checking and the operations that run after the grouping.</p>

<p>I looked at a few databases to see how they implement grouping. SQL database implementations tend to have speed as their goal rather than the simplicity and readability of the code which can make them hard to follow. <a href="https://github.com/h2database/h2database">H2</a> is one of the few that isn’t written in a low level C-like language.</p>

<p>An insight that helps implement aggregation is how databases that process data in rows usually use an accumulator to calculate the result a row at a time rather than trying to process a whole column of data at once.</p>

<h3 id="the-sql-standard">The SQL standard</h3>

<p>I have wanted to take a look at the SQL standard for a while to clarify some behaviour, but didn’t want to pay the hundreds it costs to purchase the standard. I went to the <a href="https://savoyplace.theiet.org/member-facilities/the-library/">Library at the IET</a> (The Institution of Engineering and Technology) which lets you view many standards through their network. They are open to the public for free and was a nice place to work from for the day.</p>

<p>The standard was also helpful in confirming the exact meaning of certain terms and making it clear where implementations have the freedom to do their own thing.</p>

<h3 id="hytradboi-conference">HYTRADBOI conference</h3>

<p>I spent Friday watching talks from <a href="https://www.hytradboi.com/2025">HYTRADBOI</a>. Since the talks were about databases and programming languages, I can’t imagine a more relevant conference for me.</p>

<p>My favourite talks were “<a href="https://www.hytradboi.com/2025/0a4d08fd-149e-4174-a752-20e9c4d965c5-a-quick-ramp-up-on-ramping-up-quickly">A quick ramp-up on ramping up quickly</a>” (about the tradeoff between optimizing for initial run time and later runs in javascript engines), and “<a href="https://www.hytradboi.com/2025/419859c5-6a8f-4a49-b324-0f225e083114-a-case-for-feminism-in-programming-language-design">A case for feminism in programming language design</a>”.</p>

<p>I also learnt about the <a href="https://www.hytradboi.com/2025/f8582cd3-1e39-43a8-8749-46817b2910cf-pipe-syntax-in-sql-its-time">pipe-syntax that is now available to use in BigQuery</a> and the <a href="https://www.hytradboi.com/2025/03580e19-4646-4fba-91c3-17eaba6935b0-throwing-it-all-away---how-extreme-rewriting-changed-the-way-i-build-databases">process of building things by throwing them away</a>.</p>

<p>My lightning talk <a href="https://www.hytradboi.com/2025/b479d9ff-3dd9-4548-940d-24698e7cff71-learning-about-the-odd-bits-of-sql-by-reading-the-postgresql-docs">on the odd bits of SQL is also available</a>.</p>

<h3 id="updated-chapter-list">Updated chapter list</h3>

<p>Going through the sample implementation again has helped me break up the guide into sensible chunks. I’ve updated the chapter list <a href="https://technicaldeft.com/build-a-database-server">on the landing page for the guide</a>. Most of my time in the next few weeks will be writing the remaining chapters for part one of the guide.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Web-first and making PDFs]]></title>
    
      <link href="http://chriszetter.com/blog/2025/02/16/booknotes-web-first-and-pdfs/"/>
    
    <updated>2025-02-16T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/02/16/booknotes-web-first-and-pdfs</id>
    <content type="html"><![CDATA[<p>Booknotes 5.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="progress">Progress</h3>
<p>This week I’ve continued with my sample implementation so it can handle filtering, sorting, limiting and joins. I’ve also written a chapter about references.</p>

<h3 id="building-web-first">Building web-first</h3>

<p>I’m mildly frustrated when technical books are only available in a fixed-size PDF or in a non-so-nicely formatted ebook. My plan for the book is to first publish it as a website. The web is great at looking good at different screen sizes and is very easy to make updates to. To do this, I’m writing the each chapter as a <a href="https://support.google.com/docs/answer/15499791?hl=en-GB&amp;co=GENIE.Platform%3DDesktop">tab</a> in a Google Doc and have a process that <a href="https://support.google.com/docs/answer/12014036?hl=en-GB#zippy=%2Cexport-a-google-doc-as-markdown">exports the document as markdown</a> and then renders it as HTML with <a href="https://kramdown.gettalong.org/">Kramdown</a>.</p>

<h3 id="making-a-pdf">Making a PDF</h3>

<p>Although I am building for the web, I did want to make sure I could turn the book into a PDF that looks good in case there was any need for an offline version. I first tried printing the page as a PDF from Chrome. I knew Chrome Dev tools had a way to change the CSS media type to print but it took me a while to find it. It seems like the Chrome engineers do love <a href="https://stackoverflow.com/questions/9540990/using-chromes-element-inspector-in-print-preview-mode#answer-29962072">moving the setting around</a> every few releases. The wording of the menu and setting has even changed since the Stack Overflow answer.</p>

<p>I fixed some visual issues in a new print stylesheet. I made use of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside"><code class="language-plaintext highlighter-rouge">break-inside</code></a> for the first time to keep certain elements together on the same page. I used the Chrome print dialog to save a PDF, I’ll likely automate it if I need to do it again.</p>

<h3 id="consistent-chapters">Consistent chapters</h3>

<p>One thing I’m doing at the moment is making sure the chapters are all of a similar size and can be implemented in a similar amount of code. I’ve moved a few things from the main implementation into optional ‘extensions’ section that each chapter has to help balance things out.</p>

<p>One example is inserting items into explicit columns (e.g <code class="language-plaintext highlighter-rouge">INSERT INTO t1 (b, a) VALUES (2, 1);</code> instead of <code class="language-plaintext highlighter-rouge">INSERT INTO t1 VALUES (1, 2);</code>). This feature added a bit of complexity early on to the implementation and no later features relied on it- I think it’s much more rewarding to have features you can use and build upon in later chapters.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Parsing and tokenization]]></title>
    
      <link href="http://chriszetter.com/blog/2025/02/01/booknotes-parsing-and-tokenization/"/>
    
    <updated>2025-02-01T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/02/01/booknotes-parsing-and-tokenization</id>
    <content type="html"><![CDATA[<p>Booknotes 4.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="progress">Progress</h3>
<p>This week I’ve continued with my sample implementation which has helped me to go back and improve the first four chapters.</p>

<h3 id="a-new-chapter-appears">A new chapter appears</h3>

<p>In my last booknotes I said that I’ve restarted my sample implementation so I can go through the test-suite as someone following the guide for the first time would. This has been a great way to evaluate the existing chapters to make sure they have a clear focus and the right amount of complexity.</p>

<p>It was very satisfying to find there was a whole whole chapter related to parsing that was previously muddled into three other chapters. This week I’ve written this chapter which I’ve called ‘Resilient parsing’ and goes into detail about mixed capitalization, extra whitespace and identifiers that overlap with keywords. It suggests using tokenization to help manage this complexity.</p>

<h3 id="simpler-tokenization">Simpler tokenization</h3>

<p>And focusing on parsing made me realise that I had overcomplicated the regular expressions I was using in my tokenizer. Previously I used regular expressions to break up the input like this:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">keyword</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">KEYWORD_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:keyword</span><span class="p">,</span> <span class="n">keyword</span><span class="p">.</span><span class="nf">upcase</span><span class="p">)</span>
<span class="k">elsif</span> <span class="n">identifier</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">IDENTIFIER_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:identifier</span><span class="p">,</span> <span class="n">identifier</span><span class="p">)</span>
<span class="k">elsif</span> <span class="n">symbol</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">SYMBOL_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:symbol</span><span class="p">,</span> <span class="n">symbol</span><span class="p">)</span>
<span class="k">elsif</span> <span class="n">integer</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">INTEGER_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:integer</span><span class="p">,</span> <span class="n">integer</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<p>The problem was that keywords (such as <code class="language-plaintext highlighter-rouge">SELECT</code>, <code class="language-plaintext highlighter-rouge">insert</code>, <code class="language-plaintext highlighter-rouge">WHERE</code>) and identifiers (such as <code class="language-plaintext highlighter-rouge">my_column</code>, <code class="language-plaintext highlighter-rouge">TABLE_B</code> or <code class="language-plaintext highlighter-rouge">selected_value</code>) look very similar and the only way to distinguish between them is to use a look-ahead in the regular expression to make sure a keyword isn’t followed by another character or underscore. I also didn’t like how changing the order of the conditions would break the parser because the identifier regular expression didn’t exclude keywords. Put another way, it was hard to make all my regular expressions <em>exclusive</em> of each other.</p>

<p>I found I could avoid this just by matching on a pattern that matched keywords AND identifiers and then checking if the match was in a list of keywords:</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">word</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">WORD_PATTERN</span><span class="p">)</span>
   <span class="k">if</span> <span class="no">KEYWORDS</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="n">word</span><span class="p">.</span><span class="nf">upcase</span><span class="p">)</span>
     <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:keyword</span><span class="p">,</span> <span class="n">word</span><span class="p">.</span><span class="nf">upcase</span><span class="p">)</span>
   <span class="k">else</span>
     <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:identifier</span><span class="p">,</span> <span class="n">word</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">elsif</span> <span class="n">symbol</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">SYMBOL_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:symbol</span><span class="p">,</span> <span class="n">symbol</span><span class="p">)</span>
<span class="k">elsif</span> <span class="n">integer</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="no">INTEGER_PATTERN</span><span class="p">)</span>
   <span class="no">Token</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:integer</span><span class="p">,</span> <span class="n">integer</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>

<h3 id="enumerators-without-next">Enumerators without next</h3>

<p>I was looking at using enumerators in my sample implementation and found that certain kinds of enumerators in Ruby don’t have the <code class="language-plaintext highlighter-rouge">next</code> and related methods available.</p>

<p><a href="https://bugs.ruby-lang.org/issues/21089">I submitted a bug to Ruby for the problem</a>. There is likely some reason that product and chain enumerators have been implemented differently to regular enumerators, but I can’t work out why. I’m hoping that they could be made more similar or at least the documentation improved to explain the difference.</p>

<h3 id="talk">Talk</h3>

<p>I still would like to submit a lightning talk for <a href="https://lrug.org/meetings/2025/february/">February’s LRUG</a> but I’m away for some of next week so don’t think I will have the time. Either way I will be there to watch the other talks.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Talks]]></title>
    
      <link href="http://chriszetter.com/blog/2025/01/25/booknotes-talks/"/>
    
    <updated>2025-01-25T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/01/25/booknotes-talks</id>
    <content type="html"><![CDATA[<p>Booknotes 3.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="progress">Progress</h3>
<p>I’ve written more on the chapter on joining data and made improvements to the test runner.</p>

<h3 id="talks">Talks</h3>

<p>I’ve submitted a lighting talk to <a href="https://www.hytradboi.com/2025">HYTRADBOI</a>. The slightly-silly talk goes some of the shade the PostgreSQL documentation throws on the SQL standard.</p>

<p>I also have an idea for a talk about implementing part of a database server that I might submit to LRUG for February.</p>

<h3 id="restarting-my-implementation">Restarting my implementation</h3>

<p>I’ve restarted my sample implementation so I can go through the test-suite as someone following the guide for the first time would. I haven’t started completely from scratch since I’m re-using chunks from my previous implementation.</p>

<p>This has led me to add better error handling so even unexpected errors are formatted sensibly and a feature that prints out tests that have passed for the first time. I’ve also added some automated tests for the test suite itself that run as a Github Action against different Python versions.</p>

<p>Since I’ve rearranged a few chapters, this process has also let me build a git history that better matches the order of the guide.</p>

<h3 id="iterators">Iterators</h3>

<p>I’m deciding when I should introduce iterators in the guide. Many real databases use the iterator pattern to process different parts of the SELECT queries. Iterators let you pull in data as it’s needed. This avoids redundant processing and has lower memory requirements compared to running each part of the query in sequence.</p>

<p>In the first part of the guide I want to discourage people thinking from about performance of queries and working on optimizations that might make their implementation harder to change. In some ways iterators are an optimization but I’m trying to decide if they are also <a href="https://tomstu.art/a-lever-for-the-mind">a more helpful abstraction</a> for processing data that could lead to more understandable solutions.</p>

<h3 id="goal-for-february">Goal for February</h3>

<p>By the end of February I’d like to have the guide at the point where I can share it with a few people that can try it out.</p>

<p>The main things I want to do before then are:</p>
<ul>
  <li>Write last two chapters on aggregate functions and grouping</li>
  <li>Complete sample implementation for all chapters</li>
</ul>

<p>The things I’d like to do:</p>
<ul>
  <li>Have a chapter/section about using iterators to process queries</li>
  <li>Write implementation hints for every chapter</li>
</ul>

<p>And the things I think I can leave to later:</p>
<ul>
  <li>Write an introduction about SQL</li>
  <li>Complete all diagrams</li>
  <li>Write an appendixes about working on the test suite and ideas for bigger extensions</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: A bag of tuples]]></title>
    
      <link href="http://chriszetter.com/blog/2025/01/11/booknotes-a-bag-of-tuples/"/>
    
    <updated>2025-01-11T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/01/11/booknotes-a-bag-of-tuples</id>
    <content type="html"><![CDATA[<p>Booknotes 2.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<h3 id="progress">Progress</h3>
<p>This week I’ve been working on two chapters, the first is about implementing filtering, sorting and limiting data (with <code class="language-plaintext highlighter-rouge">WHERE</code>, <code class="language-plaintext highlighter-rouge">ORDER BY</code> and <code class="language-plaintext highlighter-rouge">LIMIT</code>) and the second is about joining data.</p>

<h3 id="researching">Researching</h3>
<p>A question I’ve tried to answer this week is why the syntax for <code class="language-plaintext highlighter-rouge">CAST</code> is <code class="language-plaintext highlighter-rouge">CAST(value AS type)</code> and not just <code class="language-plaintext highlighter-rouge">CAST(value, type)</code> like other functions in SQL. I’ve read people suggesting that the <code class="language-plaintext highlighter-rouge">AS</code> improves readability, but I’m not sure I believe that as an answer. My reckon is that it’s because most other functions take values and type references such as <code class="language-plaintext highlighter-rouge">INTEGER</code> or <code class="language-plaintext highlighter-rouge">BOOLEAN</code> aren’t values.</p>

<p>Finding reasons behind decisions like this can be tricky for SQL as many of them happened in the 70s. <code class="language-plaintext highlighter-rouge">CAST</code> did come later in the 1992 SQL specification, but was in some implementations before then. It’s not that important to know, but I was curious and I feel that I owe a justification to readers as to why parsing <code class="language-plaintext highlighter-rouge">CAST</code> will be that little bit different to other functions.</p>

<h3 id="surprising-behaviour">Surprising behaviour</h3>

<p>I was surprised as to how references in <code class="language-plaintext highlighter-rouge">ORDER BY</code> clauses get resolved. For example:</p>

<p><code class="language-plaintext highlighter-rouge">SELECT -id AS id FROM orders ORDER BY id;</code></p>

<p><code class="language-plaintext highlighter-rouge">SELECT -id AS id FROM orders ORDER BY id + 0;</code></p>

<p>These return rows in <strong>different orders</strong> in SQLite, PostgreSQL and MySQL. Turning <code class="language-plaintext highlighter-rouge">id</code> in the <code class="language-plaintext highlighter-rouge">ORDER BY</code> clause from just a reference into an expression causes the column to be used rather than the value from the select list.</p>

<p>MySQL and SQLite allow you to use named items from the select list within <code class="language-plaintext highlighter-rouge">ORDER BY</code> expressions when there are no clashes, but PostgreSQL doesn’t (e.g: <code class="language-plaintext highlighter-rouge">SELECT id AS x FROM orders ORDER BY -x;</code>). I’m assuming it’s meant to behave this way. I couldn’t find this in the documentation for any of the databases I looked at, I’m yet to delve into the SQL specification and could also check the source code of some databases to confirm the behaviour.</p>

<h3 id="language">Language</h3>
<p>I’m <a href="/blog/2015/05/25/the-name-of-the-class/">a strong believer of finding the right name</a>. When describing databases, there are lots of overloaded words<sup id="fnref:database" role="doc-noteref"><a href="#fn:database" class="footnote" rel="footnote">1</a></sup>, or words that don’t quite fit in all situations. An example of this is talking about what is being joined with <code class="language-plaintext highlighter-rouge">JOIN</code>. The easy answer is tables, but this isn’t always accurate. You could join a view, or join to already joined data.</p>

<p>Relational algebra would describe it as a  <em>relation</em> but strictly relations are sets of tuples that can’t contain duplicate rows. Also, in my experience, the word ‘relations’ isn’t commonly used by application developers. I haven’t yet settled on what I should call it. I could stick with ‘table’, but with an explanation. I could be vague and call it ‘data’ or a ‘dataset’. Tabular data? Table-like? A collection of rows? A bag of tuples?</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:database" role="doc-endnote">
      <p>‘Database’ has to be the most overloaded word, referring to a database management system, a database server, a set of tables, multiple sets of tables, persistent files that store tables or any structured collection of data. <a href="#fnref:database" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Booknotes: Writing portable code]]></title>
    
      <link href="http://chriszetter.com/blog/2025/01/04/booknotes-writing-portable-code/"/>
    
    <updated>2025-01-04T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2025/01/04/booknotes-writing-portable-code</id>
    <content type="html"><![CDATA[<p>Booknotes 1.</p>

<p>I’m writing <a href="https://technicaldeft.com/build-a-database-server">a guide to building your own database server</a>. Here’s what I’ve been doing:</p>

<ul>
  <li><strong>Progress</strong> - My aim is to get the first part of the guide in a releasable state by April. I’ve written 6 of the 10ish chapters so far and have a rough outline for the rest.</li>
  <li><strong>Portable code</strong>  - The book comes with tests to help guide your implementation. So that the tests are as easy to run as possible for most people I’ve chosen to write the test runner in python. Python is widely used, is included with many Linux distributions by default and has an installer for OSX. By having zero dependencies and by targeting a broad range of python 3 versions I hope to reduce any faff that people will have to go through to run the tests. I considered writing the tests in JavaScript/TypeScript and <a href="https://bun.sh/docs/bundler/executables">using Bun to make a distributable executable</a> but think I prefer to keep the test runner code more visible and easily editable by people. I’ve spent some time over the last weeks adding to the test runner so that it formats failures better and can run individual test cases.</li>
  <li><strong>Diagrams</strong> - I’ve been deciding what tool to draw the diagrams for the guide in. I’d like the tool to be able to export SVGs with a transparent background so that the diagrams look good at different sizes and can work on light and dark backgrounds. The top two contenders are <a href="https://www.tldraw.com">tldraw</a> and <a href="https://www.figma.com/figjam/">FigJam</a>. Both make it easy to create diagrams with arrows that snap to boxes. I like the ‘sketchy’ look that diagrams from tldraw have but it’s very restrictive on customization such as with colours and font sizes. FigJam is a little more customizable, but has to be pasted into Figma before it can be exported as an SVG. Here’s an example that shows how to structure a parser that can work with statements such as <code class="language-plaintext highlighter-rouge">SELECT 1, TRUE, FALSE;</code> <a href="/assets/booknotes/tldraw.svg">made in tldraw</a> and <a href="/assets/booknotes/figjam.svg">FigJam</a>. Let me know if you prefer the look of one over the other or have a suggestion for another tool I should try.</li>
  <li><strong>Typing</strong> - The last chapter I wrote was about catching errors and typing statements. In each chapter I call out any interesting differences and implementation choices in different database engines. I learned that SQLite has chosen to be much more <a href="https://www.sqlite.org/flextypegood.html">flexible</a> when it comes to types compared to other databases, for example <code class="language-plaintext highlighter-rouge">"23dogs" / "5"</code> will happily evaluate to <code class="language-plaintext highlighter-rouge">4</code>.  SQLite is the JavaScript of databases - it’s everywhere and will do whatever it can to coerce types rather than give an error.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Using the mob tool for productive pairing]]></title>
    
      <link href="http://chriszetter.com/blog/2023/05/14/productive-pairing-with-the-mob-tool/"/>
    
    <updated>2023-05-14T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2023/05/14/productive-pairing-with-the-mob-tool</id>
    <content type="html"><![CDATA[<p><em>This post is based on a talk I gave at LRUG in February 2023, <a href="https://lrug.org/meetings/2023/february/">which you can stream</a>.</em></p>

<p>I started using the remote mob and pair programming tool <strong>mob</strong> with my team. I’ll explain what the tool does and how it helps to maintain momentum and productivity while pairing.</p>

<p>I’m a big fan of pair and mob programming. It’s the quickest way to share knowledge, skills and make progress on many problems. I’m always looking for ways that the pairing experience can be better; how can you remove friction so that it’s easy for engineers to work on the same thing at the same time? And how can you make sure the experience is engaging for everyone and one person it’s hogging the keyboard?</p>

<h3 id="what-can-make-paring-frustrating">What can make paring frustrating?</h3>

<p>There are a few things that can make pairing no fun at all:</p>

<h4 id="using-someone-elses-editor">Using someone else’s editor</h4>
<p>Using a different editor with different extensions and shortcuts is difficult. If you work remotely, waiting for each keystroke to travel across the world will be laggy.</p>

<h4 id="switching-infrequently">Switching infrequently</h4>
<p>If you switch drivers infrequently, people can disengage and won’t have an understanding or ownership of a problem. Skills and power imbalances can make this worse. A senior engineer might hog the keyboard, stopping more junior engineers from being able to explore the problem and contribute.</p>

<h4 id="breaking-your-flow">Breaking your flow</h4>
<p>Just like you want fast feedback from running tests so you don’t interrupt your flow, you want to be able to switch drivers quickly without losing focus on your work. And if switching drivers is hard, you’ll do it less often.</p>

<p>So you might have a better time if you can pair while using your own editor with frequent switches and without breaking flow.</p>

<h2 id="the-mob-tool">The mob tool</h2>

<p>Mob is a command line tool that helps you pair and mob programming.</p>

<p>It uses Git to help manage the branch you’re mobbing on. And it works well for a pair of two people up to mobbing in larger groups.</p>

<p>Mob helps solve common frustrations with pairing by helping you have frequent and smooth handovers while letting you use your own editor. Mob is designed to work with remote pairing, so sharing a single machine might work better if you’re in the same room with someone.</p>

<p>Most time you use mob, you’ll be using three commands:</p>

<p><strong><code class="language-plaintext highlighter-rouge">mob start 10 </code></strong>starts or continues a mob session on the current branch with a 10-minute timer. The way that this works is that mob will create a temporary  branch prefixed with ‘mob’.</p>

<p><strong><code class="language-plaintext highlighter-rouge">mob next </code></strong>pushes your work to a work-in-progress commit, ready for the next person.</p>

<p><strong><code class="language-plaintext highlighter-rouge">mob done </code></strong>ends the mob session by squashing your commits together, ready for you to review and write a commit message. It also removes the temporary mob branch.</p>

<p>You can <a href="https://github.com/remotemobprogramming/mob/#fast-git-handover-with-mob">learn more about using mob on its project page</a>.</p>

<h2 id="making-sure-you-switch-frequently">Making sure you switch frequently</h2>

<p>Mob reminds you to switch by playing a sound. You choose the handover time. I’ve found 10 minutes works well, and sessions flow best if you try to stick to the timer. One exception is that switching a minute earlier or later can be better if it coincides with you making a test pass or writing a new failing one.</p>

<p>Having a timer solves so many problems - forgetting to switch or feeling embarrassed to ask to switch because you are stuck. The magic of mob is that it’s easy to set the timer as part of switching.</p>

<h2 id="easy-handovers">Easy handovers</h2>

<p>Mob gives you easy handovers with <code class="language-plaintext highlighter-rouge">mob start</code> and <code class="language-plaintext highlighter-rouge">mob next</code>. You don’t have to think; just run the commands, and mob will handle it.</p>

<p>Mob will also tell you who’s next by looking at the session history. Useful for keeping track of the rotation if you’re working in larger groups.</p>

<p>And mob will open the last modified file in your editor if you have the <code class="language-plaintext highlighter-rouge">MOB_OPEN_COMMAND</code> set, stopping any fumbling to find the right file.</p>

<p>All these things feel small, but having a speedy and reliable handover process means you don’t lose pace when you switch drivers. If switching frequently, an efficient handover process becomes more important.</p>

<p>You could do some of what mob does yourself by managing your own branch in Git, but it won’t be as easy as using the mob command, and you won’t get the other useful features.</p>

<h2 id="what-using-mob-feels-like">What using mob feels like</h2>

<p>I’ve found that pairing and mobbing sessions with mob have more momentum. By this, I mean that because everyone gets to type, and each interval is short, it’s more engaging and feels like you’re going faster. Someone I work with described it as ‘Energy boosting, rather than energy sapping’.</p>

<p>I’ve also found that because mob provides structure to your coding sessions, it’s easy for someone to join or leave a mob session without disruption.</p>

<p>Mob’s default is to make a work-in-progress commit when you switch and then squash them together when you finish. If you like making small and well-described commits as you work, you can still do this with mob. Commit on your branch as you’re working on it, and make sure you set  <code class="language-plaintext highlighter-rouge">MOB_DONE_SQUASH</code> to <code class="language-plaintext highlighter-rouge">no-squash</code> or <code class="language-plaintext highlighter-rouge">squash-wip</code> so that these commits aren’t lost when a run <code class="language-plaintext highlighter-rouge">mob done</code>.</p>

<h2 id="give-mob-a-try">Give mob a try</h2>

<p>If you work remotely with others, <a href="https://github.com/remotemobprogramming/mob#fast-git-handover-with-mob">give mob a go</a>!</p>

<p>Experiment with different timer lengths. The default of 10 minutes is a good amount of time for me. You might find different timings work well for you depending on how many people you are working with and what you’re working on.</p>

<p>I recommend working to optimise your handover time. Using mob is the first step to do this, mob has <a href="https://github.com/remotemobprogramming/mob#best-practices">suggestions on how to configure it and other practices to follow for the smoothest of handovers</a>.</p>

<h3 id="read-more">Read more</h3>

<p><strong><a href="https://github.com/remotemobprogramming/mob">mob tool on GitHub</a></strong></p>

<p><strong><a href="https://www.remotemobprogramming.org">Remote Mob Programming</a></strong> - Best practices from the creators of the mob tool</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My cookbook]]></title>
    
      <link href="http://chriszetter.com/blog/2020/12/27/My-cookbook/"/>
    
    <updated>2020-12-27T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/12/27/My-cookbook</id>
    <content type="html"><![CDATA[<p>There are so many recipes on the web, all competing for keywords. When I find one that I like, and is easy to follow, and uses ingredients that are easy to come by, AND doesn’t measure <a href="https://www.wikihow.com/Measure-Butter">butter by volume</a>, I want to make sure I save it.</p>

<p>When I gave <a href="https://chriszetter.com/blog/2019/10/26/a-visit-to-kew-gardens-and-a-baking-failure/">writing weeknotes</a> a go this year, I liked having a place that I could record and make notes on the the recipes I had made. After I stopped writing weeknotes I wanted for another way I could do this.</p>

<p><strong>I have started to collect <a href="https://chriszetter.com/cookbook/">recipes in my cookbook</a></strong>. Everything in there comes highly recommended with a five-star/‘I would make this again!’ rating.</p>

<p>The cookbook itself made up of <a href="https://gist.github.com/zetter/19bbb19de2181fbfaebef70ecbb012ad">jekyll posts</a> - metadata about the recipes are stored as YAML, and my comments are in markdown. So that I don’t need to fear that my favourite cookie recipe might be lost forever, I <a href="https://gist.github.com/zetter/6679b0744331803b81163475b9db66d1">made a script that makes a local copy of all the recipes I link to</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Generating random maps]]></title>
    
      <link href="http://chriszetter.com/blog/2020/06/26/generating-random-maps/"/>
    
    <updated>2020-06-26T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/06/26/generating-random-maps</id>
    <content type="html"><![CDATA[<p>After <a href="/blog/2020/06/25/mapping-anything-with-bsicons/">learning about the BSicons</a> that Wikipedia uses to build route maps for transport systems, I wanted to see if I could use BSicons in randomly generated maps.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/shanghai-metro-line-4.png" alt="A diagram of the circular line 4 that shows the route of the metro alongside station names and connecting rail services" />
    
  <figcaption>A route map of <a href="https://en.wikipedia.org/wiki/Line_4_(Shanghai_Metro)">Line 4 of the Shanghai Metro</a> that has been built with BSicons.</figcaption>
</figure>

<h2 id="automatic-matching">Automatic matching</h2>

<p>I wanted to include as many different BSicons as possible in my generated maps.
I made a copy of all the BSicons from Wikipedia and created a script to analyse them. By examining the pixels in the icon the script would categorize each edge. I used this later to decide if two icons could ‘fit’ together. The strategy for map generation was to:</p>

<ol>
  <li>Place a random icon in the centre of the grid</li>
  <li>For each empty tile in a spiral from the centre, find a tile where the edges of the tile matched with the edges of all adjacent placed tiles</li>
</ol>

<p>This was a good start and made some interesting maps. However, the way I was determining if icons could fit together wasn’t very reliable. It meant that many icons were never be placed because they had no matches. While icons with curves wouldn’t visually match to the icons they were placed next to.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/road-rail.png" alt="A partially filled grid of icons showing a road and some rail lines" />
    
  <figcaption>An early random map I generated. The [?] icons show where my code was unable to find a icon that fitted in the gap.</figcaption>
</figure>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/lattice.png" alt="A filled grid of icons showing train lines going under and over each other in a diagonal lattice." />
    
  <figcaption>This is my favourite image my code produced. It uses only a few tiles to create a complex maze-like pattern that reminded me of <a href="https://10print.org"><code>10 PRINT</code></a>.</figcaption>
</figure>

<h2 id="less-is-more">Less is more</h2>

<p>By reducing the number of BSicons I was working with, it became feasible for me to manually categorise what tiles could fit together. I changed to using the <a href="https://robertheaton.com/2018/12/17/wavefunction-collapse-algorithm/">wavefunction collapse algorithm</a> to place the tiles. The wavefunction collapse algorithm prioritizes placing tiles in the spaces with the greatest restriction on them. This reduces situations where the algorithm can’t place anything and gets stuck.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/two-lines.png" alt="Icons placed in a grid showing two overlapping train lines" />
    
  <figcaption>An early map I generated with this method. The algorithm has no understanding of what the icons themselves mean so it can produce maps that are unlikely to exist such as a train line with no stations.</figcaption>
</figure>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/more-icons.png" alt="Icons placed in a grid showing two overlapping train lines with tunnels and roads." />
    
  <figcaption>I slowly introduced more kinds of icons into my generated maps.</figcaption>
</figure>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons-random/tiled.png" alt="Icons placed in a grid showing rail lines and roads that go past the edge of the image" />
    
  <figcaption>I changed the generator to make tiled maps that could be repeated. With this extra restriction, the generation doesn't always work. If no more tiles can be placed before the grid is filled it starts again.</figcaption>
</figure>

<p>I really like the interconnected and overlapping routes the generator can make. You can use it to <strong><a href="https://mapmaker.chriszetter.com">generate your own maps</a></strong>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Mapping anything with BSicons]]></title>
    
      <link href="http://chriszetter.com/blog/2020/06/25/mapping-anything-with-bsicons/"/>
    
    <updated>2020-06-25T10:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/06/25/mapping-anything-with-bsicons</id>
    <content type="html"><![CDATA[<style>
.bsicon-info {
  font-size: 0.93em;
  margin: 20px 0 10px 0;
  background-color: #EEE;
  padding: 10px;
  border-radius: 3px;
  border: 1px solid #DDD;
}

.bsicon {
  width: 50px !important;
  height: 50px;
  display: inline-block;
}

.bsicon-info b {
  font-weight: bold;
}

.bsicon-info header {
  display: flex;
  align-items: center;
}

.bsicon-info p {
  padding: 8px 0 8px 0;
}

.bsicon-info h3 {
  margin-top: 0;
  margin-left: 10px;
  display: inline-block;

}
</style>

<p>If you go to the Wikipedia page for the <a href="https://en.wikipedia.org/wiki/Forth_and_Clyde_Canal">Forth and Clyde Canal</a>, the <a href="https://en.wikipedia.org/wiki/Trans-Siberian_Railway">Trans-Siberian Railway</a> or <a href="https://en.wikipedia.org/wiki/Circle_line_(London_Underground)">the London Circle Line</a> you may notice that they all have route maps with a similar visual style.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons/glasgow_subway_bsicons.png" alt="A diagram of the Glasgow subway loop that shows the route of the subway alongside station names and connecting rail services" />
    
  <figcaption>A route map of the <a href="https://en.wikipedia.org/wiki/Glasgow_Subway">Glasgow subway</a> from Wikipedia.</figcaption>
</figure>

<p>How do the many Wikipedia contributors create all these similar-looking maps? The answer is <strong>BSicons</strong>.</p>

<h2 id="bsicons">BSicons</h2>

<p><a href="https://commons.wikimedia.org/wiki/BSicon">BSicons</a> are the building blocks for these route maps. They are an SVG icon set that Wikipedia contributors use to map railways, subways, footpaths, waterways, cycle paths and roads. Any transport system that they want to produce a simplified schematic for.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons/glasgow_subway_bsicon_grid.png" alt="A diagram of the Glasgow subway. The diagram is made up of square icons in a grid which is highlighted" />
    
  <figcaption>The Glasgow subway map is made up of many BSicons icons. Most are square, but there are a few half-width icons too that allow for a more compact map.</figcaption>
</figure>

<p>The icons were first used on the German Wikipedia which is why most of their names are based on German words.
‘BSicons’ comes from the German word Bahnstrecken (Railway Lines).</p>

<p>Each icon has a shorthand name that follows some conventions:</p>
<ul>
  <li>A <strong>Root</strong> picks a given icon such as a station or a crossing.</li>
  <li><strong>Prefixes</strong> change it’s status, such as if it’s underground or disused.</li>
  <li><strong>Suffixes</strong> denote direction and positioning, such as if it curves to the left or is one way.</li>
</ul>

<p>Here are some of the icons:</p>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_STR.svg" />
    <h3 class="title">STR</h3>
  </header>
  <p>A rail line</p>
  Root: <b>STR</b> → <b>STR</b>eke (line)
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_WASSER.svg" />
    <h3 class="title">WASSER</h3>
  </header>
  <p>A river or other waterway</p>
  Root: WASSER (water)
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_KRZu.svg" />
    <h3 class="title">KRZu</h3>
  </header>
  <p>Two rail lines crossing with one going under the other</p>
  Root: <b>KRZ</b> → <b>KR</b>eu<b>Z</b>ung (crossing)<br />
  Suffix: <b>u</b> → <b>u</b>nter (under)
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_STR%2Bl.svg" />
    <h3 class="title">STR+l</h3>
  </header>
  <p>A rail line that comes from the left</p>
  Root: <b>STR</b> → <b>STR</b>eke (line)<br />
  Suffix: <b>+l</b> → <b>+</b> (from), <b>l</b>inks (left)<br />
  <p> Directions are relative to the line (which is drawn from top to bottom) rather than the page. This is why the suffix says the line is from the left rather than going to the right.</p>
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_utkBHF%2B1.svg" />
    <h3 class="title">utkBHF+1</h3>
  </header>
  <p>A station on an underground light rail line that comes from the first corner</p>
  Root: <b>BHF</b>  →  <b>B</b>ahn<b>H</b>o<b>F</b> (station)<br />
  Prefix: <b>utk</b> → <b>u</b>-bahn, <b>t</b>unnel, <b>k</b>ombination (Compound)<br />
  <p>the <b>k</b> denotes that the icon is for drawing compound turns that span four columns of icons.</p>
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_RP2r.svg" />
    <h3 class="title">RP2r</h3>
  </header>
  <p>A two-lane paved road with a roundabout</p>
  Root: <b>RP2</b> → <b>R</b>oad <b>P</b>aved <b>2</b>-lane<br />
  Suffix: <b>r</b>  → <b>r</b>oundabout<sup id="fnref:clash"><a href="#fn:clash" class="footnote">1</a></sup><br />
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_tSTRa.svg" />
    <h3 class="title">tSTRa</h3>
  </header>
  <p>A rail line that goes into a tunnel</p>
  Root: <b>STR</b> → <b>STR</b>eke (line)
  Prefix: <b>t</b> → <b>t</b>unnel<br />
  Suffix: <b>a</b> → <b>a</b>nfang (start)
</div>

<div class="bsicon-info">
  <header>
    <img class="bsicon" src="/assets/bsicons/BSicon_mhKRZho.svg" />
    <h3 class="title">mhKRZho</h3>
  </header>
  <p>An elevated rail line going over a light elevated rail line</p>
  Root: <b>KRZ</b> → <b>KR</b>eu<b>Z</b>ung (crossing)<br />
  Prefix: <b>mh</b> → <b>m</b>ischbetrieb (mixed), <b>h</b>ochbahn (high level/elevated)<br />
  Suffix: <b>ho</b> → <b>h</b>ochbahn (high level/elevated), <b>o</b>verpass
</div>

<p>These are a few examples. The <a href="https://commons.wikimedia.org/wiki/BSicon/Catalogue">BSicon Catalogue</a> explains many more conventions.</p>

<h2 id="building-maps">Building maps</h2>

<p>To help put all these icons together into a map Wikipedia has a <a href="https://en.wikipedia.org/wiki/Template:Routemap">Routemap template</a>. The template defines a syntax to provide shortcuts to build maps.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons/glasgow_subway_bsicons_row.png" alt="A diagram of the Glasgow subway loop that shows one line of icons highlighted." />
    
  <figcaption>Routemaps are made up of rows of icons </figcaption>
</figure>

<p>Here is the code used to generate the single highlighted row:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
{{Subway|Hillhead}}! !\utkBHF+1\\\utkBHF+4\tSTRa~~{{Subway|St George's Cross}}

</code></pre></div></div>

<p>The syntax is a bit cryptic and uses the shorthand icons names we saw above. Here is what each part does:</p>

<ul>
  <li><strong><code>&#123;&#123;Subway|Hillhead}}</code></strong> is a link to the Wkipedia article about this station</li>
  <li><strong><code class="language-plaintext highlighter-rouge">! !</code></strong> separates the text on the left from the icons</li>
  <li><strong><code class="language-plaintext highlighter-rouge">\utkBHF+1</code></strong> is the first icon a light rail station in a tunnel that curves</li>
  <li><strong><code class="language-plaintext highlighter-rouge">\\</code></strong> adds in two empty icon-sized spaces</li>
  <li><strong><code class="language-plaintext highlighter-rouge">\utkBHF+4</code></strong> adds in the second icon, similar to the last but towards top-left corner</li>
  <li><strong><code class="language-plaintext highlighter-rouge">\tSTRa</code></strong> adds in the third icon, a start of a stretch of tunnel</li>
  <li><strong><code class="language-plaintext highlighter-rouge">~~~</code></strong> separates the icons from the text on the right</li>
  <li><strong><code>&#123;&#123;Subway|St George's Cross}}</code></strong>  a link to the Wikipedia article about this station.</li>
</ul>

<h2 id="hundreds-of-thousands-of-icons">Hundreds of thousands of icons</h2>

<p>There are <a href="https://commons.wikimedia.org/w/index.php?title=Special:Search&amp;search=File%3A+intitle%3A%22BSicon%22+intitle%3A%2FBSicon+.%2A%5C.svg%2F&amp;ns0=1&amp;ns6=1&amp;ns12=1&amp;ns14=1&amp;ns100=1&amp;ns106=1">more than 290,000 BSicons</a> out there due to an explosive number of combinations needed for different colours, rotations, intersections, bridges, curves, embankments and tunnels. Many obscure BSicons might only be used a few times across Wikipedia (like <a href="https://commons.wikimedia.org/wiki/File:BSicon_BHFABZgl%2Bl.svg">BHFABZgl+l</a>)<sup><a href="#fn:triangle" class="footnote">2</a></sup>.</p>

<p>Each icon is simple, so simple many of them are marked as ineligible for copyright on Wikipedia. Together the icons can combine to map more complex systems.
Seeing how these icons can be combined inspired me to make a <strong><a href="https://mapmaker.chriszetter.com">random BSicon map generator</a></strong>.</p>

<figure class="image-figure center-smaller switch">
  
    <img src="/assets/bsicons/tiles-random-2.png" alt="A gird of icons showing train lines crossing over and under each other with stations." />
    
  <figcaption>A random tiling image made by my <a href="https://mapmaker.chriszetter.com">random map generator</a></figcaption>
</figure>

<div class="footnotes">
  <ol>
    <li id="fn:clash">
      <p>The use of r for roundabout <a href="https://commons.wikimedia.org/wiki/Talk:BSicon/Renaming/Archive_11#Suffix_reuse">clashes with the use of r for right that's used with other root icons</a>. If you want a road goes to the right you need to use <strong>rf</strong> (<strong>r</strong>ight <strong>f</strong>orward) instead. While many prefixes and suffixes work the same way across multiple roots it's not a perfect system.</p>
    </li>
    <li id="fn:triangle">
      <p>This icon is used to represent triangular railway stations <a href="https://osm.org/go/evjLogw1u--">such as Shipley</a>. There are only two of these stations in the UK.</p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Lockdown activities]]></title>
    
      <link href="http://chriszetter.com/blog/2020/04/26/lockdown-activies/"/>
    
    <updated>2020-04-26T15:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/04/26/lockdown-activies</id>
    <content type="html"><![CDATA[<p>Weeknotes 14.</p>

<ul>
  <li><strong>Mapping</strong> - I live close to the <a href="https://www.north-herts.gov.uk/norton-common">Norton Common nature reserve</a> in Letchworth. Over the last few visits I’ve explored more of it so I can <a href="https://twitter.com/czetter/status/1253998193777545217">improve it on Open Street Map</a>. I’m quite happy with where it’s at now, especially compared to the two paths mapped <a href="https://www.google.co.uk/maps/@51.9852886,-0.2310219,16z">on Google’s version</a></li>
  <li><strong>Offsite</strong> - Farewill usually has off-sites every couple of months. We had a virtual one this time around and was nice to get to speak to some of the newer joiners in the company. We split into much smaller groups and then split again into teams. It worked so much better than having all of us in a single Zoom meeting would have.</li>
  <li><strong>Immutable objects</strong> - This week at work, I wished that none of the functions on JavaScript standard objects modified the receiver. I’ve seen it cause too many bugs</li>
  <li><strong>Plants</strong>  - <a href="https://www.instagram.com/p/B_ZUG6MHxlB/">I took a cutting from my Chinese Money plant</a> which is doing well in a jar of water. I don’t understand why plants that need well-drained soil can also thrive in just water, I would love to know the answer but searching has lead me nowhere. Less happy is my Aloe Vera. I moved it to a sunnier sunny spot for it’s own benefit to see it go brown in sun-shock.</li>
  <li><strong>Baking</strong> - As well as seeing <a href="https://www.instagram.com/beckysveganbakes/">some of the amazing things my sister has baked</a>, I’ve made a <a href="https://veggiedesserts.com/courgette-cake/">Lemon  Drizzle Courgette cake</a> and <a href="https://hedgecombers.com/spiced-pear-muffins/">Spiced Pear Muffins</a>. Both of these are butter-less - <a href="https://www.saltfatacidheat.com/buy-book">Salt, Fat, Acid, Heat</a> made me realise that I prefer the moistness and texture of oil-based cakes.</li>
  <li><strong>Wavelength Remote</strong> - I adapted <a href="https://www.wavelength.zone">Wavelength</a> so I could play it remotely with friends until <a href="https://www.wavelength.zone/app">the creators launch their app</a>. It involved multiple cameras and asking people to close their eyes at certain points. It kinda worked. A friend has made a <a href="https://balancetheload.co/social-distance/">remote-friendly web-based game</a> that uses a similar mechanic.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Hair, birds and trains]]></title>
    
      <link href="http://chriszetter.com/blog/2020/04/13/hair-birds-and-trains/"/>
    
    <updated>2020-04-13T15:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/04/13/hair-birds-and-trains</id>
    <content type="html"><![CDATA[<p>Weeknotes 13.</p>

<ul>
  <li><strong>Bird Table</strong> - I put a GoPro in the garden and <a href="https://www.instagram.com/p/B-m7NoopzsM/">filmed a couple of birds</a> that I tempted on-camera with some dried mealworms. The blue tit is in half-speed since it was barely there at all.</li>
  <li><strong>Hair</strong> - <a href="https://www.instagram.com/p/B-7LWZnJxCY/">MY FRINGE IS OUT OF CONTROL</a>. I’m using two hair clips to keep it out of my eyes. I don’t feel brave enough to trim it myself yet.</li>
  <li><strong>Baking</strong> - I made some more port-brownies and a <a href="https://www.bbcgoodfood.com/recipes/rhubarb-strawberry-crumble-custard">rhubarb crumble</a> with <a href="https://www.leiths.com/blog/thick-vanilla-custard">custard</a>. It’s useful being able to use my weeknotes to remember what particular recipe I used a few months ago.</li>
  <li><strong>Isolation Realisations</strong> - I miss the act of travelling - going to work, walking to the shops, shuffling between meeting rooms. Never in my adult life have I not been on a train for such a long stretch.</li>
  <li><strong>Easter Egg Hunt</strong> - Pauline surprised me with a <a href="https://twitter.com/the_richey/status/1249273354982428673">puzzle-based easter egg hunt</a> which was lots of fun. I was especially impressed with the crossword grid and want to try making one myself.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Lower latency]]></title>
    
      <link href="http://chriszetter.com/blog/2020/03/29/lower-latency/"/>
    
    <updated>2020-03-29T16:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/03/29/lower-latency</id>
    <content type="html"><![CDATA[<p>Weeknotes 12.</p>

<ul>
  <li><strong>Crossword improvements</strong> - I’ve had some lovely messages from people who are enjoying using <a href="https://multicrosser.chriszetter.com">Several People are Solving</a>. I’ve also seen the traffic jump from 10 people a day a month ago to more than 250 people a day now. I’ve spent a bit more time on it and there are now more links to crosswords from the home page. I want to colour-in moves so you can see who made them, but I’m not sure the best way to do it to have some continuity for a user’s colour across games but also avoid clashing. I’d like not to have to create an account system either.</li>
  <li><strong>Lower latency</strong> - In pursuit of more reliable video calls and lower-latency <a href="https://www.nvidia.com/en-gb/geforce-now/">Geforce Now</a> I set up a <a href="https://www.netgear.co.uk/home/products/networking/powerline/default.aspx">Powerline</a> ethernet connection which works great. I’ve played more Cities Skylines and I’m likely hours away from buying the <a href="https://store.steampowered.com/app/1146930/Cities_Skylines__Sunset_Harbor/">Sunset Harbour expansion</a> that was released this week.</li>
  <li><strong>Keeping a routine</strong> - After spending a whole week either at my desk working or on the sofa watching TV, I felt unenergised and my days began blurring together. I’ve instead tried to go for a walk before starting work to help refresh myself and get me out of bed on time and doing indoor-exercise in the evening using <a href="https://fitonapp.com/">FitOn</a> or a cross-trainer.</li>
  <li><strong>Splitting strings</strong> - Skills matter and their library of videos is <a href="https://twitter.com/skillsmatter/status/1243183726101532674">back online</a>! I made a copy of my <a href="https://skillsmatter.com/skillscasts/11029-splitting-strings">Splitting Strings</a> video for safekeeping.  I re-read some of the <a href="https://www.reddit.com/r/programming/comments/79hhsh/the_surprising_behaviour_of_calling_split_on/">discussion about my talk and post on Reddit</a>. The, perhaps not explicit enough, point of the talk was about the surprising complexity of seemingly simple functions and how there can be logical reasons this complexity and differing behaviour. So much of the discussion devolves into what programming language is ‘right’ or ‘wrong’. Oh well.</li>
  <li><strong>Veg</strong> - We found our nearby farm shop has a bountiful supply of vegetables that our local supermarket is missing. I also got to use my drill to help Pauline put together a raised bed so we can grow our own. We have some broccoli, cabbage and bean seedlings that are almost ready to go in.</li>
  <li><strong>Brownies</strong> - I wanted to put the last two eggs in the fridge to good use so made brownies. I usually put espresso powder and whisky since they both go so well with chocolate but instead used some port leftover from Christmas. <a href="https://glutenfreeonashoestring.com/chewy-gluten-free-brownies/">I used this recipe</a> with the addition of a medium wine-glass worth of port into the butter and sugar mix. I was VERY happy with them.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Working from home more & how toilet roll is really made]]></title>
    
      <link href="http://chriszetter.com/blog/2020/03/15/working-from-home-more-and-how-toilet-roll-is-really-made/"/>
    
    <updated>2020-03-15T16:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/03/15/working-from-home-more-and-how-toilet-roll-is-really-made</id>
    <content type="html"><![CDATA[<p>Weeknotes 11.</p>

<ul>
  <li><strong>Toilet roll</strong> - I thought I knew how it was made, but then I watched <a href="https://www.bbc.co.uk/news/av/business-51823128/coronavirus-don-t-panic-be-community-minded-says-loo-roll-boss">a clip from the BBC</a> and I’m now convinced that they steal toilet paper from giants and then use some kind of shrink-ray to ready it for consumers.</li>
  <li><strong>WFH</strong> - Starting Thursday this week we’ve been asked to work from home until further notice. I’m thinking about if there are changes we could try in our team to help us adjust to working remote more. The <a href="https://mailchi.mp/3074cde43d65/maintaining-connection-during-isolation">Maintaining connection &amp; collaboration at a time of isolation</a> email from Tessa’s Collaborative Future arrived in my inbox just in time.</li>
  <li><strong>More multiplayer crosswords</strong> - I’ve heard that at least one team is using <a href="https://multicrosser.chriszetter.com">Multicrosser</a> to do crosswords together while remote. I also had a peep at the Guardian’s new <a href="https://www.theguardian.com/membership/2020/feb/11/welcome-to-the-new-guardian-puzzles-app">Puzzles App</a> which is provided by <a href="https://amuselabs.com">Amuse Labs</a>. Excitingly, it lets you share a crossword with one other person to do real-time solving.</li>
  <li><strong>Work area improvements</strong> - I’ve spent some time this weekend tidying our spare bedroom and making it a bit more pleasant to work in. I’ve bought some soft furnishings, put up a couple of pictures and ordered posters from the <a href="https://www.ltmuseumshop.co.uk/posters">London Transport Museum</a> and <a href="https://www.ssplprints.com">Science &amp; Society Picture Library</a>.</li>
  <li><strong>Gaming</strong> - Nvidia has made their game steaming service <a href="https://www.nvidia.com/en-gb/geforce-now/">Geforce Now</a> generally available. I jumped at the chance to run <a href="https://www.paradoxplaza.com/cities-skylines/CSCS00GSK-MASTER.html">Cities: Skylines</a> which I’ve been aching to play for ages but couldn’t on my underpowered laptop. There’s an occasional stutter where everything looks like a 10%-quality JPEG, but otherwise it works really well. I’m going to see if connecting via ethernet instead of wireless improves reliability.</li>
  <li><strong>Eating</strong> - I’ve been going through all the veggie items in Morrisons freezer section, I really rate <a href="https://groceries.morrisons.com/products/morrisons-the-best-layered-vegetable-tart-493004011">The Best Layered Vegetable Tart</a> - it really is.</li>
  <li><strong>Watching</strong> - The last two <a href="https://www.bbc.co.uk/programmes/b05p650r/episodes/player">Inside No. 9 episodes</a> were my favourites of the series. Also, Bon Appétit fans will enjoy <a href="https://www.youtube.com/watch?v=eUJzqChe3FQ">an interview with a lot of the Test Kitchen</a> and “<a href="https://www.youtube.com/watch?v=l3m8rPXF5PE">Amateur Toy Maker Attempts to Make Claire Saffitz Bootleg Action Figure</a>”.</li>
  <li><strong>Spot my face</strong> - My team has rebuilt <a href="https://farewill.com/careers">our careers page</a> to be the nicest looking careers page of anywhere I’ve worked. Can you spot all the places my face appears? (hint: you need to view the page on a larger screen to see them all).</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Magic paste and the roundest animal]]></title>
    
      <link href="http://chriszetter.com/blog/2020/02/16/magic-paste-and-the-roundest-animal/"/>
    
    <updated>2020-02-16T16:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/02/16/magic-paste-and-the-roundest-animal</id>
    <content type="html"><![CDATA[<p>Weeknotes 10.</p>

<ul>
  <li><strong>Magic paste</strong> - I’m continuing with an endless stream of house chores. This week I added a towel rail and hooks to the bathroom. Next on my todo list is filling some old drill holes in the bathroom with some <a href="https://magicezy.com/magicezy-tile-repairezy-2/">magic paste</a> and researching how on earth to fit curtain rails/poles to our bay window.</li>
  <li><strong>SSL Certs</strong> - I spent some time managing my <a href="http://dokku.viewdocs.io/dokku/">Dokku-powered</a> web server. I got an email from Let’s Encrypt telling me that <a href="https://community.letsencrypt.org/t/end-of-life-plan-for-acmev1/88430">the ACME API</a> that my older version of Dokku was using would stop working in June. For self-hosted sites, the pain of managing SSL certificates has been replaced with the meta-problem of managing software that manages SSL certificates. Still, I’m appreciative of the Let’s Encrypt project and it’s nice that I got the warning email.</li>
  <li><strong>Collecting succulents</strong> - I got a pretty <a href="https://succulentsbox.com/blogs/blog/how-to-care-for-string-of-pearls">String of Pearls</a> plant at our nearby garden centre. I’m still looking for a <a href="https://en.wikipedia.org/wiki/Pilea_peperomioides">Chinese money plant</a> and something bigger to live on the floor (suggestions welcome).</li>
  <li><strong>Progression</strong> - I spent some of my time at work this week looking at <a href="https://www.progression.fyi">publicly available progression frameworks</a> as it’s something we want to introduce to help us now the engineering team has grown (there’s 10 of us now!). <a href="https://blog.songkick.com/building-a-growth-framework-2464435e9e46">My favourite is Songkick’s Growth framework</a> since it has lots of great examples that aren’t too Songkick specific.</li>
  <li><strong>Chromecast is awful</strong> - Our meeting rooms at work all use Chromecast as a way to share your laptop screen with the TV. I find it so difficult to use. If you want to share your screen rather than the current Chrome tab, you have to stop casting and start again. When you want to stop casting it’s way too easy to stop someone else’s cast in another meeting room. And then there’s all the cutting out and glitching to put up with. Jack of all trades and master of none, Google Chrome has become the iTunes of today.</li>
  <li><strong>The roundest animal</strong> - Our copy of <a href="https://www.wavelength.zone">Wavelength</a> came, me and Pauline tried the 2-player variant. You play by drawing a card which shows two extremes (such as hot &amp; cold). One player has to secretly spin the wheel so it points to somewhere between the two extremes and has to think of a word or phrase that will help others guess where the wheel is pointing too. One of the cards was ‘<a href="https://commons.wikimedia.org/wiki/File:Bébé_Phoque_de_Weddell_-_Baby_Weddell_Seal.jpg">Roundest animal</a>’ to ‘<a href="https://en.wikipedia.org/wiki/Porcupine#/media/File:PorcupineCabelasSpringfield0511.jpg">pointiest animal</a>’ which was fun to debate.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Double Double Helix Staircases]]></title>
    
      <link href="http://chriszetter.com/blog/2020/02/02/double-helix-staircases/"/>
    
    <updated>2020-02-02T16:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/02/02/double-helix-staircases</id>
    <content type="html"><![CDATA[<p>Weeknotes 9.</p>

<ul>
  <li><strong>Gatsby</strong> - I’ve been using <a href="https://www.gatsbyjs.org">Gatsby</a> a lot at work for the last few weeks. It’s a flexible static site generator that’s able to create pages from different content sources. We use it a lot with the <a href="https://www.contentful.com/">Contentful</a> API to build pages. The downside is that I find it’s GraphQL functionality less well documented and I’m unsure of what expected behaviour is for some queries. Some query operators that I wanted to use were missing (such as filtering results on the length of a property).</li>
  <li><strong>Overboard</strong> - <a href="https://www.youtube.com/playlist?list=PLaDrN74SfdT5jEs3RCI53nBUkuURSWrhq">Polygon’s Overboard</a> is one of my favourite YouTube channels. I had the giggles throughout their play of <a href="https://youtu.be/pS-XT-5R26Q">Wavelength</a> and it convinced me to <a href="https://www.wavelength.zone">order the game</a>.</li>
  <li><strong>Perfectly balanced</strong> - I was around friends this weekend playing <a href="https://www.zmangames.com/en/products/pandemic-iberia/">Pandemic Iberia</a>. We beat the game, just. The last four moves turned into a complex logic puzzle that we talked about for twenty minutes. Me and Pauline often play Pandemic with two player-cards each to make it more complex when there’s just the two of us. I’m in awe at how well balanced the game is - we often win or lose by a single turn.</li>
  <li><strong>Double helix staircase</strong> - Most days on my commute, I change from rail to the Underground at Finsbury Park. I take one of the two spiral staircases that lead to the southbound Victoria and Piccadilly line platforms. The layout of the station never made sense to me and I always struggled to know what way to turn from the stairs to the to tube platform. I found <a href="https://cdn.ianvisits.co.uk/blog/wp-content/uploads/2015/07/finsbury-park.jpg">an older plan of the station</a><sup id="fnref:plan" role="doc-noteref"><a href="#fn:plan" class="footnote" rel="footnote">1</a></sup> and it all clicked - what I thought were two stairwells was just one with a set of two stairs inside intertwined in a double-helix. If you take one stair you need to turn left onto the Victoria line at the bottom, you turn right from the other. There’s another double-helix staircase to the northbound platforms too.</li>
  <li><strong>Coding fonts</strong> - I like the look of the new <a href="https://www.jetbrains.com/lp/mono/">Jetbrains Mono</a> font but was put off trying it because of its coding <a href="https://www.jetbrains.com/lp/mono/#ligatures">ligatures</a>. I feel similar to the point <a href="https://practicaltypography.com/ligatures-in-programming-fonts-hell-no.html">in this post</a> - symbol-merging ligatures add in ambiguity which programming fonts otherwise try to avoid. I saw there is <a href="https://github.com/JetBrains/JetBrainsMono/issues/19">some demand for a non-ligature version</a> and it might be possible to <a href="https://github.com/tonsky/FiraCode/issues/633">disable all ligatures in Atom</a>. I decided to stick with <a href="https://en.wikipedia.org/wiki/Consolas">Consolas</a> for now.</li>
  <li><strong>WD40 ALL THE THINGS</strong> - I’ve been using WD40 to fix lots of stiff or squeaky door handles. I don’t understand how, but it even helped a door that wasn’t closing properly. I aspire to own as <a href="https://mudge.name/2020/01/26/weeknotes-13/">many types of WD40 as Paul Mucur</a>.</li>
</ul>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:plan" role="doc-endnote">
      <p>The plan just shows a single staircase in each of the stairwells, more recent work re-added the second (<a href="https://planning.islington.gov.uk/NorthgatePublicDocs/00223030.pdf">there’s a plan on page 8 of this PDF</a>). <a href="#fnref:plan" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Weeknotes: Rebasing and Baking]]></title>
    
      <link href="http://chriszetter.com/blog/2020/01/05/rebasing-and-baking/"/>
    
    <updated>2020-01-05T17:00:00+00:00</updated>
    <id>http://chriszetter.com/blog/2020/01/05/rebasing-and-baking</id>
    <content type="html"><![CDATA[<p>Weeknotes 8.</p>

<ul>
  <li><strong>Making it easier to rebase from Atom</strong> - This week <a href="https://atom.io">Atom 1.43</a> was released. This was exciting for me because this included a change that I made in September that <a href="https://github.com/atom/github/pull/2270">added ‘Copy Commit SHA’ and ‘Copy Commit Subject’ actions</a> to Atom’s git tab. I use git’s <a href="https://thoughtbot.com/blog/autosquashing-git-commits">auto-squashing</a> a lot and thought this would make creating ‘fixup!’ and ‘squash!’ commits easier.</li>
  <li><strong>Free-from Baking</strong> - I started the weekend with some <a href="https://www.instagram.com/p/B7dP6LPnP8q/">gluten free waffles</a> using my oven-top waffle maker and <a href="https://www.glutenfreepalate.com/gluten-free-waffle-mix-recipe/">this recipe</a>. I then made Nigella’s <a href="https://www.nigella.com/recipes/dark-and-sumptuous-chocolate-cake">vegan chocolate cake</a> which <a href="https://www.instagram.com/p/B7eXwzznzRx/">came out great</a> and helped out with a <a href="https://www.bbcgoodfood.com/recipes/spicy-harissa-aubergine-pie">spicy harissa aubergine pie</a> for Sunday lunch. We made it vegan by substituting the feta with  some <a href="https://violifefoods.com/product/violife-greek-white-block/">‘Greek white block’</a> which is the most utilitarian named foodstuff I’ve ever bought.</li>
  <li><strong>My first day off</strong> - I switched to working 9 days in every 10 this year and had my first extra ‘day off’ this week. I had high hopes for how I would spend the time but came downstairs to a leaking boiler and spent most of the day finding an emergency plumber.</li>
  <li><strong>Being a better manager</strong> - I’m reading Camille Fournier’s book <a href="http://shop.oreilly.com/product/0636920056843.do">The Manager’s Path</a>. I enjoyed reading a section that contrasts the <a href="https://books.google.co.uk/books?id=zqNaDgAAQBAJ&amp;pg=PA40&amp;dq=%22Imagined+life+of+a+senior+individual+contributor%22&amp;hl=en&amp;sa=X&amp;ved=0ahUKEwighbfimZDnAhXWQRUIHWhvCBsQ6AEIKTAA#v=onepage&amp;q=%22Imagined%20life%20of%20a%20senior%20individual%20contributor%22&amp;f=false">‘imagined’ vs ‘real’ life of individual contributors and mangers</a> which I think is a great way to show why these roles might not always meet peoples expectations. The book also gave me ideas of how to understand my reportees better so I know the best way to work with them. I set some questions for them in our 1:1s based off of <a href="https://larahogan.me/blog/first-one-on-one-questions/">the ones suggested by Lara Hogan</a>.</li>
</ul>
]]></content>
  </entry>
  
</feed>
