<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Iain Dillingham</title><link href="https://www.dillingham.me.uk/" rel="alternate"/><link href="https://www.dillingham.me.uk/feeds/all.atom.xml" rel="self"/><id>https://www.dillingham.me.uk/</id><updated>2026-04-10T00:00:00+01:00</updated><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/04/10/weeknotes.html" rel="alternate"/><published>2026-04-10T00:00:00+01:00</published><updated>2026-04-10T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-04-10:/2026/04/10/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 10th April&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a bug in production.
  The &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate didn&amp;#8217;t automatically renew.
  It expired, leaving a Cloudflare &amp;#8220;Invalid &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate&amp;#8221; message in place of OpenPrescribing v2 for about 40 minutes early this&amp;nbsp;morning.&lt;/li&gt;
&lt;li&gt;Started work on a new …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 10th April&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a bug in production.
  The &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate didn&amp;#8217;t automatically renew.
  It expired, leaving a Cloudflare &amp;#8220;Invalid &lt;span class="caps"&gt;SSL&lt;/span&gt; certificate&amp;#8221; message in place of OpenPrescribing v2 for about 40 minutes early this&amp;nbsp;morning.&lt;/li&gt;
&lt;li&gt;Started work on a new feature:
  the ability to query by form/route and ingredient in OpenPrescribing v2&amp;#8217;s backend.
  (Peter added the ability to fetch/ingest dm+d data and to fetch/ingest a mapping from dm+d codes to &lt;span class="caps"&gt;BNF&lt;/span&gt; codes.)
  I didn&amp;#8217;t finish work on it this week,
  because of the bug in&amp;nbsp;production.&lt;/li&gt;
&lt;li&gt;Finished reading Simon Willison&amp;#8217;s guide to &lt;a href="https://simonwillison.net/guides/agentic-engineering-patterns/"&gt;Agentic Engineering Patterns&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Another bug in&amp;nbsp;production&lt;/h2&gt;
&lt;p&gt;I fixed a bug in production &lt;a href="https://www.dillingham.me.uk/2026/04/03/weeknotes.html"&gt;last week&lt;/a&gt;, too.
I&amp;#8217;m not concerned that they exist or that they caused long outages;
not today, anyway.
OpenPrescribing v2 is still beta,
signalled by the subdomain and the banner at the top of the page.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;
It takes time to fit together
two reverse proxys (Cloudflare, Nginx),
&lt;span class="caps"&gt;SSL&lt;/span&gt; certificates (Let&amp;#8217;s Encrypt),
a web server (Gunicorn),
and a web application (Django).
Sometimes, a long time:
it&amp;#8217;s likely that today&amp;#8217;s bug
was caused by a change I made &lt;a href="https://www.dillingham.me.uk/2026/02/20/weeknotes.html"&gt;nearly two months&lt;/a&gt; ago
in response to an issue with OpenPrescribing&amp;nbsp;v1.&lt;/p&gt;
&lt;p&gt;More than last week,
this week I leaned heavily on &lt;a href="https://chatgpt.com/"&gt;ChatGPT&lt;/a&gt;.
I asked it to suggest reasons for the error, based on the message and code.
I asked it about Dokku and the Let&amp;#8217;s Encrypt plugin,
because it wasn&amp;#8217;t clear to me whether the error originated at the system-level or the app-level.
And when the fix we &amp;#8212; yes, ChatGPT &lt;em&gt;and&lt;/em&gt; me &amp;#8212; agreed on didn&amp;#8217;t work,
I asked it about Cloudflare&amp;#8217;s reverse proxy.
At this point, however,
I ignored its suggestions to disable Cloudflare&amp;#8217;s reverse proxy
and to use &lt;span class="caps"&gt;DNS&lt;/span&gt;-01 rather than &lt;span class="caps"&gt;HTTP&lt;/span&gt;-01,
and instead added a Cloudflare security&amp;nbsp;rule.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Respectively,
  &lt;a href="https://beta.openprescribing.net/"&gt;https://beta.openprescribing.net/&lt;/a&gt;
  and
  &amp;#8220;This is a beta version of a new OpenPrescribing&amp;#8221;.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Weeknotes"/><category term="LLMs"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/04/03/weeknotes.html" rel="alternate"/><published>2026-04-03T00:00:00+01:00</published><updated>2026-04-03T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-04-03:/2026/04/03/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 3rd April&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;Two weeks&amp;#8217; worth of weeknotes this&amp;nbsp;week.&lt;/p&gt;
&lt;p&gt;Last week I was in Oxford,
celebrating &lt;a href="https://www.ox.ac.uk/news/2025-11-26-opensafely-team-awarded-queen-elizabeth-prize-higher-and-further-education"&gt;the award of the Queen Elizabeth Prize for Higher and Further Education&lt;/a&gt;.
This coincided with my five year anniversary at the &lt;a href="https://www.bennett.ox.ac.uk/"&gt;Bennett Institute for Applied Data Science …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 3rd April&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;Two weeks&amp;#8217; worth of weeknotes this&amp;nbsp;week.&lt;/p&gt;
&lt;p&gt;Last week I was in Oxford,
celebrating &lt;a href="https://www.ox.ac.uk/news/2025-11-26-opensafely-team-awarded-queen-elizabeth-prize-higher-and-further-education"&gt;the award of the Queen Elizabeth Prize for Higher and Further Education&lt;/a&gt;.
This coincided with my five year anniversary at the &lt;a href="https://www.bennett.ox.ac.uk/"&gt;Bennett Institute for Applied Data Science&lt;/a&gt;,
which led me to reflect on my longest tech job.
Team Prescribosaurus also met up to talk about our next&amp;nbsp;cycle.&lt;/p&gt;
&lt;p&gt;Last week and this week,
I added a feature to OpenPrescribing v2:
thumbs up/thumbs down buttons for quick feedback.
Clicking either button prompts you for more information.
It took me a couple of hours to add the feature with help from Codex,
so this was the second time I&amp;#8217;ve used Codex to write code.
(&lt;a href="https://www.dillingham.me.uk/2026/02/27/weeknotes.html"&gt;The first time&lt;/a&gt; was in late February.)
But it took me a couple of &lt;em&gt;days&lt;/em&gt; to debug why it wasn&amp;#8217;t working in production,
between meetings and code reviews.
Even now,
I can&amp;#8217;t pinpoint the root cause.
I have a hypothesis,
but &lt;a href="https://github.com/bennettoxford/openprescribing-v2/pull/248"&gt;the quick fix&lt;/a&gt; makes testing it prohibitively&amp;nbsp;expensive.&lt;/p&gt;
&lt;p&gt;It seems to me that this kind of bug
&amp;#8212; works in development, doesn&amp;#8217;t work in production, insufficient context &amp;#8212;
is resilient to coding agents.
Codex and &lt;a href="https://chatgpt.com/"&gt;ChatGPT&lt;/a&gt; helped, definitely.
Looking back through my questions,
I see that I very quickly learnt a lot about &lt;a href="https://owasp.org/www-community/attacks/csrf"&gt;Cross Site Request Forgery&lt;/a&gt; (&lt;span class="caps"&gt;CSRF&lt;/span&gt;)
and &lt;a href="https://docs.djangoproject.com/en/6.0/ref/csrf/"&gt;how Django protects against it&lt;/a&gt;.
However, neither Codex nor ChatGPT were able to pinpoint the root cause.
And neither was&amp;nbsp;I.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t think this kind of bug signals a win for humans or a loss for coding agents, or vice versa.
I think it signals that coding agents can support humans by making debugging faster, more accurate, and more enjoyable (there are fewer dead ends).
Human judgement is still important, though.
Martin Fowler talked about this in &lt;a href="https://martinfowler.com/fragments/2026-04-02.html"&gt;a recent blog post&lt;/a&gt;.
I&amp;#8217;m going to read the blog post he linked to;
&amp;#8220;&lt;a href="https://ajeygore.in/content/the-expensive-thing"&gt;The Expensive Thing&lt;/a&gt;&amp;#8221; by Ajey&amp;nbsp;Gore.&lt;/p&gt;</content><category term="Weeknotes"/><category term="LLMs"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/03/20/weeknotes.html" rel="alternate"/><published>2026-03-20T00:00:00+00:00</published><updated>2026-03-20T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-03-20:/2026/03/20/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week was emotionally draining.
It ended with a moment of clarity that made me rethink the last three&amp;nbsp;months.&lt;/p&gt;
&lt;p&gt;For now,
I&amp;#8217;m going to link to three posts that Ben &lt;span class="caps"&gt;B.C.&lt;/span&gt;&amp;nbsp;recommended:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://larahogan.me/blog/creating-momentum-when-an-employee-is-stuck/"&gt;Creating momentum when an employee is …&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week was emotionally draining.
It ended with a moment of clarity that made me rethink the last three&amp;nbsp;months.&lt;/p&gt;
&lt;p&gt;For now,
I&amp;#8217;m going to link to three posts that Ben &lt;span class="caps"&gt;B.C.&lt;/span&gt;&amp;nbsp;recommended:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://larahogan.me/blog/creating-momentum-when-an-employee-is-stuck/"&gt;Creating momentum when an employee is stuck&lt;/a&gt;&amp;#8221; by Lara&amp;nbsp;Hogan;&lt;/li&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://www.rubick.com/tradeoffs-first/"&gt;First agree on the tradeoffs&lt;/a&gt;&amp;#8221; by Jade&amp;nbsp;Rubick;&lt;/li&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://www.seangoedecke.com/how-i-estimate-work/"&gt;How I estimate work as a staff software engineer&lt;/a&gt;&amp;#8221; by Sean&amp;nbsp;Goedecke.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And to two posts that I found when I was trying to understand what a &lt;em&gt;feature factory&lt;/em&gt;&amp;nbsp;is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://cutle.fish/blog/12-signs-youre-working-in-a-feature-factory"&gt;12 Signs You’re Working in a Feature Factory&lt;/a&gt;&amp;#8221; by John&amp;nbsp;Cutler;&lt;/li&gt;
&lt;li&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;&lt;a href="https://amplitude.com/blog/12-signs-youre-working-in-a-feature-factory-3-years-later"&gt;12 Signs You’re Working in a Feature Factory &amp;#8212; 3 Years Later&lt;/a&gt;&amp;#8221; by John&amp;nbsp;Cutler.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also read &amp;#8220;&lt;a href="https://alistapart.com/article/resilient-management-excerpt/"&gt;Resilient Management, An Excerpt&lt;/a&gt;&amp;#8221; by Lara Hogan
and was saddened to learn that &lt;a href="https://abookapart.com/"&gt;A Book Apart&lt;/a&gt; closed in&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;I did more than read posts this week, but as I say, it was emotionally&amp;nbsp;draining.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/03/13/weeknotes.html" rel="alternate"/><published>2026-03-13T00:00:00+00:00</published><updated>2026-03-13T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-03-13:/2026/03/13/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;continued to write&amp;nbsp;KPIs;&lt;/li&gt;
&lt;li&gt;added some extra meetings to the calendar:
  several short daily standups and a longer weekly team&amp;nbsp;meeting;&lt;/li&gt;
&lt;li&gt;gave a show-and-tell about our second three-week cycle on OpenPrescribing&amp;nbsp;v2;&lt;/li&gt;
&lt;li&gt;read &lt;a href="https://journals.sagepub.com/doi/full/10.1177/15291006211051956"&gt;a paper&lt;/a&gt; about how to …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;continued to write&amp;nbsp;KPIs;&lt;/li&gt;
&lt;li&gt;added some extra meetings to the calendar:
  several short daily standups and a longer weekly team&amp;nbsp;meeting;&lt;/li&gt;
&lt;li&gt;gave a show-and-tell about our second three-week cycle on OpenPrescribing&amp;nbsp;v2;&lt;/li&gt;
&lt;li&gt;read &lt;a href="https://journals.sagepub.com/doi/full/10.1177/15291006211051956"&gt;a paper&lt;/a&gt; about how to design effective and intuitive data&amp;nbsp;visualisations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Fixed time, variable&amp;nbsp;scope&lt;/h2&gt;
&lt;p&gt;As I mentioned &lt;a href="https://www.dillingham.me.uk/2026/03/06/weeknotes.html"&gt;last week&lt;/a&gt;,
we&amp;#8217;ve been applying techniques from &lt;a href="https://basecamp.com/shapeup"&gt;Shape Up&lt;/a&gt;.
Last week, I talked about pitches.
This week, I&amp;#8217;m going to talk about &lt;a href="https://basecamp.com/shapeup/1.2-chapter-03#fixed-time-variable-scope"&gt;fixed time, variable scope&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fixed time, variable scope&lt;/em&gt; means a team holds the time they spend on delivery constant
and varies the scope of what they deliver.
Contrast this with &lt;em&gt;fixed scope, variable time&lt;/em&gt;.
I have much (much) more experience of the latter than of the former.
In every case, &lt;em&gt;variable time&lt;/em&gt; meant taking more, not less, time.
And taking more time meant missing deadlines, again and&amp;nbsp;again.&lt;/p&gt;
&lt;p&gt;Shape Up calls the time a team spends on delivery a &lt;em&gt;cycle&lt;/em&gt;.
It suggests adopting either six-week or two-week cycles,
with a cool-down period between each cycle.
We adopted three-week cycles on OpenPrescribing v2
and, &lt;a href="https://www.dillingham.me.uk/2026/02/13/weeknotes.html"&gt;for historical reasons&lt;/a&gt;,
call the cool-down period &lt;em&gt;deck-scrubbing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been hard to finish what we&amp;#8217;ve been working on by the end of each cycle.
Although we finished our first cycle &lt;a href="https://www.dillingham.me.uk/2026/02/13/weeknotes.html"&gt;more or less on time&lt;/a&gt;,
we did some delivery work during deck-scrubbing and
we paused some delivery work that we started but didn&amp;#8217;t finish.
This &amp;#8220;overhang&amp;#8221; and &amp;#8220;unfinished business&amp;#8221; were demotivating.
We had much less of both with our second cycle,
but we discarded work that wasn&amp;#8217;t getting good feedback.
This was also demotivating, but for different reasons.
Nevertheless,
at the end of each cycle we were able to give a show-and-tell about a coherent set of features and fixes.
We were also able to describe what we discarded and explain why we discarded it,
without feeling guilty for spending too much time on&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/><category term="Shape Up"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/03/06/weeknotes.html" rel="alternate"/><published>2026-03-06T00:00:00+00:00</published><updated>2026-03-06T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-03-06:/2026/03/06/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;was reminded (again) that people issues are harder than technical&amp;nbsp;issues;&lt;/li&gt;
&lt;li&gt;started writing some&amp;nbsp;KPIs;&lt;/li&gt;
&lt;li&gt;started writing another&amp;nbsp;pitch;&lt;/li&gt;
&lt;li&gt;read &lt;a href="https://htmx.org/essays/yes-and/"&gt;a blog post about LLMs&lt;/a&gt; by the creator of &lt;a href="https://htmx.org/"&gt;htmx&lt;/a&gt;.
  (Thank you for the link,&amp;nbsp;Simon.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pitches&lt;/h2&gt;
&lt;p&gt;In …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th March&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;was reminded (again) that people issues are harder than technical&amp;nbsp;issues;&lt;/li&gt;
&lt;li&gt;started writing some&amp;nbsp;KPIs;&lt;/li&gt;
&lt;li&gt;started writing another&amp;nbsp;pitch;&lt;/li&gt;
&lt;li&gt;read &lt;a href="https://htmx.org/essays/yes-and/"&gt;a blog post about LLMs&lt;/a&gt; by the creator of &lt;a href="https://htmx.org/"&gt;htmx&lt;/a&gt;.
  (Thank you for the link,&amp;nbsp;Simon.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pitches&lt;/h2&gt;
&lt;p&gt;In early November last year,
the tech leads started talking about &lt;a href="https://basecamp.com/shapeup"&gt;Shape Up&lt;/a&gt;.
You might have heard of it.
Shape Up contains a collection of product development techniques that are,
according to the book&amp;#8217;s &lt;a href="https://basecamp.com/shapeup/0.3-chapter-01"&gt;introduction&lt;/a&gt;,
tried and tested by Basecamp, now &lt;a href="https://37signals.com/"&gt;37signals&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Central to the book is the idea that a delivery team should only start a piece of work
when it has been properly &lt;em&gt;shaped&lt;/em&gt;.
Shaping is less like a planning activity and more like a design activity.
The result of shaping a piece of work is a &lt;em&gt;pitch&lt;/em&gt;.
A pitch&amp;nbsp;should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;describe the&amp;nbsp;problem;&lt;/li&gt;
&lt;li&gt;state the &lt;em&gt;appetite&lt;/em&gt;,
  or the amount of time a team should spend delivering the&amp;nbsp;solution;&lt;/li&gt;
&lt;li&gt;contain a low-fidelity representation of the&amp;nbsp;solution;&lt;/li&gt;
&lt;li&gt;state any rabbit holes and&amp;nbsp;no-goes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ve written four pitches for OpenPrescribing v2.
None are original;
all draw on existing material.
However, I&amp;#8217;ve found that by using more-or-less the same structure,
it&amp;#8217;s getting easier to write, and to discuss, each&amp;nbsp;pitch.&lt;/p&gt;
&lt;p&gt;My main difficulty, so far,
has been to identify both a problem and a solution that will occupy three senior software engineers for 270 hours.
Estimation was hard before LLMs arrived;
it&amp;#8217;s even harder now, because writing code is quick and easy
(&lt;a href="https://www.dillingham.me.uk/2026/02/27/weeknotes.html"&gt;for a senior software engineer&lt;/a&gt;, at least).
Things that seem easy end up being hard;
things that seem hard end up being&amp;nbsp;easy.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/><category term="Shape Up"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/02/27/weeknotes.html" rel="alternate"/><published>2026-02-27T00:00:00+00:00</published><updated>2026-02-27T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-02-27:/2026/02/27/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 27th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week felt like a tipping point:
I started using an &lt;span class="caps"&gt;LLM&lt;/span&gt; to write&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;Before this week, I&amp;#8217;d used &lt;a href="https://chatgpt.com/"&gt;ChatGPT&amp;#8217;s web app&lt;/a&gt; to ask &amp;#8220;How do I?&amp;#8221;&amp;nbsp;questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do I count the number of NaN values in …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 27th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week felt like a tipping point:
I started using an &lt;span class="caps"&gt;LLM&lt;/span&gt; to write&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;Before this week, I&amp;#8217;d used &lt;a href="https://chatgpt.com/"&gt;ChatGPT&amp;#8217;s web app&lt;/a&gt; to ask &amp;#8220;How do I?&amp;#8221;&amp;nbsp;questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do I count the number of NaN values in a numpy&amp;nbsp;array?&lt;/li&gt;
&lt;li&gt;How do I parse a date string into&amp;nbsp;a &lt;code&gt;Date&lt;/code&gt; object in&amp;nbsp;JavaScript?&lt;/li&gt;
&lt;li&gt;How do I run a command for every commit in a&amp;nbsp;range?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are questions that at some point or other I&amp;#8217;ve answered myself.
Sometimes I&amp;#8217;ve read the docs.
Sometimes I&amp;#8217;ve Googled some keywords and sifted through the results.
Often I&amp;#8217;ve done both.
Alas, I&amp;#8217;ve forgotten the answers
and whilst I&amp;#8217;d like to refresh my numpy, JavaScript, and Git knowledge,
I need the answers &lt;em&gt;now&lt;/em&gt;.
In some cases, that&amp;#8217;s because I want to do the right thing before moving on:
a mistake when counting the number of NaN values would mean more time spent debugging;
incorrectly parsing a date string would mean a bug.
In others, that&amp;#8217;s because I&amp;#8217;m scratching an itch:
I could checkout each commit and run the command,
but is there a better way?
I&amp;#8217;m not going to spend my evenings and weekends finding out.
I&amp;#8217;m 44 and have a young family.
I don&amp;#8217;t have evenings and&amp;nbsp;weekends.&lt;/p&gt;
&lt;p&gt;That was before this week.
This week,
I used Codex to write code.
You&amp;#8217;re looking at it now.
I used Codex to write the &lt;span class="caps"&gt;HTML&lt;/span&gt; and &lt;span class="caps"&gt;CSS&lt;/span&gt; for my website.
I could have written it myself,
but I don&amp;#8217;t write much &lt;span class="caps"&gt;HTML&lt;/span&gt; and &lt;span class="caps"&gt;CSS&lt;/span&gt; day-to-day
and I don&amp;#8217;t have a clear picture of what good front-end code looks&amp;nbsp;like.&lt;/p&gt;
&lt;p&gt;At work, I also used Codex to write front-end code,
but with &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt;.
The Bootstrap docs are excellent: easy to navigate, loads of examples.
But I wanted a modal and as with the &amp;#8220;How do I?&amp;#8221; questions,
I wanted to do the right thing before moving on.
Incorrectly nesting&amp;nbsp;a &lt;code&gt;.modal&lt;/code&gt; within&amp;nbsp;a &lt;code&gt;.modal-dialog&lt;/code&gt; would mean a bug (they&amp;#8217;re the other way around).
I don&amp;#8217;t have evenings and weekends.
I need the answers &lt;em&gt;now&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I reviewed the code for my website and the modal just as I would review the code in a &lt;span class="caps"&gt;PR&lt;/span&gt;.
My sense is that Codex has a much clearer picture of what good front-end code looks like than I do.
I learnt a lot, but I feel uneasy.
Some&amp;nbsp;thoughts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are the environmental impacts of using&amp;nbsp;LLMs?&lt;/li&gt;
&lt;li&gt;And the social impacts?
  There are haves and&amp;nbsp;have-nots.&lt;/li&gt;
&lt;li&gt;And the legal impacts?
  LLMs can write good front-end code because they&amp;#8217;ve been trained on open-source&amp;nbsp;projects.&lt;/li&gt;
&lt;li&gt;Do LLMs disproportionately benefit me, a senior software engineer?
  &lt;a href="https://dl.acm.org/doi/10.1145/3779312"&gt;It seems so&lt;/a&gt;. (Thank you for the link,&amp;nbsp;Katie.)&lt;/li&gt;
&lt;li&gt;What are the security implications of using LLMs?
  Codex can read the contents of&amp;nbsp;my &lt;code&gt;.env&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;What are the &lt;a href="https://www.benkuhn.net/blub/"&gt;blub studies&lt;/a&gt; implications of using LLMs?
  Detailed mental models are valuable;
  fiddly technical details&amp;nbsp;aren&amp;#8217;t?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/><category term="LLMs"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/02/20/weeknotes.html" rel="alternate"/><published>2026-02-20T00:00:00+00:00</published><updated>2026-02-20T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-02-20:/2026/02/20/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;We started our second three-week cycle on OpenPrescribing v2 this week.
We&amp;#8217;re focusing on &amp;#8220;more effective visualisations&amp;#8221;.
However, I spent much of this week fixing, or trying to fix, OpenPrescribing v1.
Its &lt;span class="caps"&gt;VM&lt;/span&gt; frequently runs out of &lt;span class="caps"&gt;CPU&lt;/span&gt; and memory …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;We started our second three-week cycle on OpenPrescribing v2 this week.
We&amp;#8217;re focusing on &amp;#8220;more effective visualisations&amp;#8221;.
However, I spent much of this week fixing, or trying to fix, OpenPrescribing v1.
Its &lt;span class="caps"&gt;VM&lt;/span&gt; frequently runs out of &lt;span class="caps"&gt;CPU&lt;/span&gt; and memory,
and heavy traffic probably isn&amp;#8217;t the&amp;nbsp;cause.&lt;/p&gt;
&lt;p&gt;This week,
I also read a post about &lt;a href="https://martinfowler.com/bliki/HostLeadership.html"&gt;host leadership&lt;/a&gt; by Martin Fowler.
It reassured me that my misgivings about servant leadership weren&amp;#8217;t&amp;nbsp;misplaced.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/02/13/weeknotes.html" rel="alternate"/><published>2026-02-13T00:00:00+00:00</published><updated>2026-02-13T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-02-13:/2026/02/13/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;As I mentioned &lt;a href="https://www.dillingham.me.uk/2026/02/06/weeknotes.html"&gt;last week&lt;/a&gt;,
we&amp;#8217;re working on OpenPrescribing v2.
We finished a cycle last Friday and will start a cycle next Monday.
This week was a deck-scrubbing week;
time between cycles to tidy&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve certainly mixed and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;As I mentioned &lt;a href="https://www.dillingham.me.uk/2026/02/06/weeknotes.html"&gt;last week&lt;/a&gt;,
we&amp;#8217;re working on OpenPrescribing v2.
We finished a cycle last Friday and will start a cycle next Monday.
This week was a deck-scrubbing week;
time between cycles to tidy&amp;nbsp;up.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve certainly mixed and matched our terminology.
&lt;em&gt;Cycle&lt;/em&gt; comes from &lt;a href="https://basecamp.com/shapeup"&gt;Shape Up&lt;/a&gt;;
&lt;em&gt;deck-scrubbing&lt;/em&gt; from a time when we
thought a nautical metaphor was a good idea
and referred to a cycle as a &lt;em&gt;voyage&lt;/em&gt;.
Terminology aside,
we were asked to spend three weeks working on a feature,
then show the feature to the Bennett Institute.
I&amp;#8217;m really pleased that we did just that, more or&amp;nbsp;less.&lt;/p&gt;
&lt;p&gt;In our retro (more mixing and matching our terminology),
we talked about how we&amp;#8217;d changed our behaviour to finish the cycle on time.
Not quite:
we did a small amount of work on Monday,
so we also talked about how we wouldn&amp;#8217;t have changed our behaviour,
had we known.
During the retro,
we talked about how we&amp;#8217;re going to taper our next cycle
to make the three-week cycle to one-week deck-scrubbing transition&amp;nbsp;easier.&lt;/p&gt;
&lt;p&gt;I feel much better prepared for our next cycle.
It&amp;#8217;s good to start it knowing that we finished our last cycle more or less on&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read the Management 101 and Tech Lead chapters in
  &lt;a href="https://www.oreilly.com/library/view/the-managers-path/9781491973882/"&gt;The Manager&amp;#8217;s Path&lt;/a&gt;, by Camille&amp;nbsp;Fournier;&lt;/li&gt;
&lt;li&gt;learned that sequencing and prioritising are&amp;nbsp;different;&lt;/li&gt;
&lt;li&gt;started writing another &lt;a href="https://basecamp.com/shapeup/1.5-chapter-06"&gt;pitch&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/02/06/weeknotes.html" rel="alternate"/><published>2026-02-06T00:00:00+00:00</published><updated>2026-02-06T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-02-06:/2026/02/06/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;thought about when a user is a&amp;nbsp;user;&lt;/li&gt;
&lt;li&gt;started writing &lt;a href="https://basecamp.com/shapeup/1.5-chapter-06"&gt;a pitch&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;thought about what happens when &amp;#8220;there&amp;#8217;s not enough space on the dance&amp;nbsp;floor&amp;#8221;;&lt;/li&gt;
&lt;li&gt;learned about &lt;a href="https://en.wikipedia.org/wiki/Servant_leadership"&gt;servant leadership&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;was reminded (again) that people issues are harder …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th February&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;thought about when a user is a&amp;nbsp;user;&lt;/li&gt;
&lt;li&gt;started writing &lt;a href="https://basecamp.com/shapeup/1.5-chapter-06"&gt;a pitch&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;thought about what happens when &amp;#8220;there&amp;#8217;s not enough space on the dance&amp;nbsp;floor&amp;#8221;;&lt;/li&gt;
&lt;li&gt;learned about &lt;a href="https://en.wikipedia.org/wiki/Servant_leadership"&gt;servant leadership&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;was reminded (again) that people issues are harder than technical&amp;nbsp;issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;When is a user a&amp;nbsp;user?&lt;/h2&gt;
&lt;p&gt;We&amp;#8217;re working on OpenPrescribing v2.
Dave and Peter built a walking skeleton at the end of last year,
which Peter, Tom, and I took over at the start of this year.
We&amp;#8217;ve shown it to &lt;a href="https://www.dillingham.me.uk/2026/01/09/weeknotes.html"&gt;the OpenPrescribing network&lt;/a&gt;,
to Rich,
and to the Clinical Informaticians (a word my spelling dictionary refuses to recognise).
Next week, we&amp;#8217;re showing it to anyone in the Bennett Institute who can spare an hour on Tuesday&amp;nbsp;afternoon.&lt;/p&gt;
&lt;p&gt;During one of these show-and-tell sessions Chris,
one of the aforementioned Clinical Informaticians,
recreated &lt;a href="https://openprescribing.net/measure/doacs_nhse/definition/"&gt;a measure&lt;/a&gt; from v1 in v2.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;
This was really encouraging:
when someone does something in the new thing that they could do in the old thing,
then that&amp;#8217;s evidence that the new thing is, in some sense, working.
This made me think about whether Chris was a user of v2.
He&amp;#8217;d learned how to recreate a measure in the new thing;
he&amp;#8217;d used the new thing to complete a task!
And &lt;em&gt;this&lt;/em&gt; made me think:
how much effort should we go to,
to ensure that Chris doesn&amp;#8217;t have to relearn how to recreate a measure in the new thing
when we inevitably make changes to the new&amp;nbsp;thing?&lt;/p&gt;
&lt;p&gt;As it happened, Peter was midway through making changes to the new thing.
He was replacing a text-based interface with a point-and-click interface
that had a couple of modal windows and modifier keys.
I suggested placing the changes behind a feature flag.
I felt that asking Chris to relearn the interface,
at least until we&amp;#8217;d thought more about the modals and modifiers,
would cost a small amount of goodwill.
Peter felt that doing so was unnecessary.
Asking Chris to relearn the interface wouldn&amp;#8217;t cost that much goodwill.
And after all, OpenPrescribing v2 isn&amp;#8217;t a mature&amp;nbsp;product.&lt;/p&gt;
&lt;p&gt;In the end, we compromised.
We asked Chris to recreate a measure using the point-and-click interface.
Chris did so:
he used the even newer thing to complete a task that he completed with the new thing
and with the old thing!
We shared the point-and-click interface using &lt;a href="https://zrok.io/"&gt;zrok&lt;/a&gt;,
so we didn&amp;#8217;t need to place the changes behind a feature flag.
(Maybe zrok &lt;em&gt;is&lt;/em&gt; a feature flag?)
We may have earned a small amount of goodwill,&amp;nbsp;too.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Chris didn&amp;#8217;t completely recreate the measure,
  because it required more information than was available.
  However, he came as close as he could.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/01/30/weeknotes.html" rel="alternate"/><published>2026-01-30T00:00:00+00:00</published><updated>2026-01-30T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-01-30:/2026/01/30/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 30th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;realised that I&amp;#8217;d started, and not finished, half a dozen books on tech&amp;nbsp;leadership/management;&lt;/li&gt;
&lt;li&gt;read a lovely blog post from Will Larson about &lt;a href="https://lethain.com/should-include-eng-in-eng-leadership/"&gt;including engineers in leadership meetings&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;realised that the &lt;a href="https://untools.co/eisenhower-matrix/"&gt;Eisenhower Matrix&lt;/a&gt; works well for …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 30th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;realised that I&amp;#8217;d started, and not finished, half a dozen books on tech&amp;nbsp;leadership/management;&lt;/li&gt;
&lt;li&gt;read a lovely blog post from Will Larson about &lt;a href="https://lethain.com/should-include-eng-in-eng-leadership/"&gt;including engineers in leadership meetings&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;realised that the &lt;a href="https://untools.co/eisenhower-matrix/"&gt;Eisenhower Matrix&lt;/a&gt; works well for people, but not so well for&amp;nbsp;teams;&lt;/li&gt;
&lt;li&gt;read a lovely blog post from Julia Evans about &lt;a href="https://jvns.ca/blog/2026/01/27/some-notes-on-starting-to-use-django/"&gt;learning an Old Boring Technology&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;felt as though I couldn&amp;#8217;t keep up with the management &lt;em&gt;and&lt;/em&gt; engineering sides of being a tech&amp;nbsp;lead;&lt;/li&gt;
&lt;li&gt;felt as though I didn&amp;#8217;t know what a tech lead was,&amp;nbsp;anyway.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tech leadership/management&amp;nbsp;books&lt;/h2&gt;
&lt;p&gt;Although I&amp;#8217;ve been a tech lead for over a year,
most days feel like my first day.
I don&amp;#8217;t feel I&amp;#8217;m bad at the job; but I don&amp;#8217;t feel I&amp;#8217;m good at the job either.
My tried-and-tested approach to getting better at something is to read a book about it.
So, over the last year I&amp;#8217;ve started half a dozen books on tech leadership/management.
In alphabetical order by title, they&amp;nbsp;are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.debuggingteams.com/"&gt;Debugging Teams&lt;/a&gt;, by Ben Collins-Sussman and Brian&amp;nbsp;Fitzpatrick&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.engmanagement.dev/"&gt;Engineering Management for the Rest of Us&lt;/a&gt;, by Sarah&amp;nbsp;Drasner&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/leading-effective-engineering/9781098148232/"&gt;Leading Effective Engineering Teams&lt;/a&gt;, by Addy&amp;nbsp;Osmani&lt;/li&gt;
&lt;li&gt;&lt;a href="https://press.stripe.com/scaling-people"&gt;Scaling People&lt;/a&gt;, by Claire Hughes&amp;nbsp;Johnson&lt;/li&gt;
&lt;li&gt;&lt;a href="https://direct.mit.edu/books/monograph/5782/Smart-ManagementHow-Simple-Heuristics-Help-Leaders"&gt;Smart Management&lt;/a&gt;, by Jochen Reb, Shenghua Luan, and Gerd&amp;nbsp;Gigerenzer&lt;/li&gt;
&lt;li&gt;&lt;a href="https://teamtopologies.com/book"&gt;Team Topologies&lt;/a&gt; by Matthew Skelton and Manuel&amp;nbsp;Pais&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.oreilly.com/library/view/the-managers-path/9781491973882/"&gt;The Manager&amp;#8217;s Path&lt;/a&gt;, by Camille&amp;nbsp;Fournier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alas, I&amp;#8217;ve not finished them.
I don&amp;#8217;t wish to criticise these books:
they&amp;#8217;re well written,&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; well produced, and draw on the authors&amp;#8217; experience.
However, after several hours in each other&amp;#8217;s company, the book and I drift&amp;nbsp;apart.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don&amp;#8217;t want a book-length treatment of tech leadership/management.
  I want something like &lt;a href="https://untools.co/"&gt;untools&lt;/a&gt; (&amp;#8220;Tools for better&amp;nbsp;thinking&amp;#8221;).&lt;/li&gt;
&lt;li&gt;I want something that&amp;#8217;s well written and thoughtful.
  I have &lt;a href="https://www.bloomsbury.com/uk/thinking-of-answers-9781408809532/"&gt;Thinking of Answers&lt;/a&gt;, by &lt;span class="caps"&gt;A.C.&lt;/span&gt; Grayling in mind.
  Good blog posts can be both, but tend toward&amp;nbsp;first-cuts.&lt;/li&gt;
&lt;li&gt;I want something that isn&amp;#8217;t over-fitted to the authors&amp;#8217; experience.
  Whilst there are valuable lessons from Google and Stripe,
  I work for neither Google nor Stripe.
  My current team has three software developers; my last team, two.
  One of those software developers is/was&amp;nbsp;me.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alas, I don&amp;#8217;t have time to write more.
But something is better than&amp;nbsp;nothing.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Okay, &lt;em&gt;mostly&lt;/em&gt; well written.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/01/23/weeknotes.html" rel="alternate"/><published>2026-01-23T00:00:00+00:00</published><updated>2026-01-23T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-01-23:/2026/01/23/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 23rd January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;My weeknotes for this week are shorter than usual.
I try to start writing them on Tuesday or Wednesday,
but it&amp;#8217;s Friday afternoon and I&amp;#8217;m just&amp;nbsp;starting.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;was an incident&amp;nbsp;coordinator;&lt;/li&gt;
&lt;li&gt;learned even more about &lt;span class="caps"&gt;BNF …&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 23rd January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;My weeknotes for this week are shorter than usual.
I try to start writing them on Tuesday or Wednesday,
but it&amp;#8217;s Friday afternoon and I&amp;#8217;m just&amp;nbsp;starting.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;was an incident&amp;nbsp;coordinator;&lt;/li&gt;
&lt;li&gt;learned even more about &lt;span class="caps"&gt;BNF&lt;/span&gt;&amp;nbsp;codes;&lt;/li&gt;
&lt;li&gt;helped establish some norms about code&amp;nbsp;reviews;&lt;/li&gt;
&lt;li&gt;wondered where my week had&amp;nbsp;gone.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Incident&amp;nbsp;coordinator&lt;/h2&gt;
&lt;p&gt;When a software developer notices that there&amp;#8217;s something wrong with one of our systems,
they declare an incident in a dedicated Slack channel.
Other software developers then help to resolve the incident.
To keep them focused,
the incident coordinator communicates with everyone who isn&amp;#8217;t helping to resolve the incident:
mostly users, but also other software&amp;nbsp;developers.&lt;/p&gt;
&lt;p&gt;This week, Katie noticed that there was something wrong with &lt;a href="https://jobs.opensafely.org/"&gt;OpenSafely Jobs&lt;/a&gt;.
She declared an incident and, after a short while, resolved it.
I was the incident coordinator.
So far, so unremarkable.
But that&amp;#8217;s the point:
It takes time and effort to make things&amp;nbsp;unremarkable.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/01/16/weeknotes.html" rel="alternate"/><published>2026-01-16T00:00:00+00:00</published><updated>2026-01-16T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-01-16:/2026/01/16/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 16th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;went to Oxford for the OpenPrescribing kick-off&amp;nbsp;meeting;&lt;/li&gt;
&lt;li&gt;wrote two ADRs (Architectural Decision&amp;nbsp;Records);&lt;/li&gt;
&lt;li&gt;learned more about &lt;a href="https://duckdb.org/"&gt;DuckDB&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;learned more about &lt;a href="https://en.wikipedia.org/wiki/British_National_Formulary"&gt;&lt;span class="caps"&gt;BNF&lt;/span&gt;&lt;/a&gt;&amp;nbsp;codes;&lt;/li&gt;
&lt;li&gt;wrote&amp;nbsp;issues;&lt;/li&gt;
&lt;li&gt;caught a&amp;nbsp;cold.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ADRs&lt;/h2&gt;
&lt;p&gt;I want to write a little about ADRs,
because …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 16th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week,&amp;nbsp;I:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;went to Oxford for the OpenPrescribing kick-off&amp;nbsp;meeting;&lt;/li&gt;
&lt;li&gt;wrote two ADRs (Architectural Decision&amp;nbsp;Records);&lt;/li&gt;
&lt;li&gt;learned more about &lt;a href="https://duckdb.org/"&gt;DuckDB&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;learned more about &lt;a href="https://en.wikipedia.org/wiki/British_National_Formulary"&gt;&lt;span class="caps"&gt;BNF&lt;/span&gt;&lt;/a&gt;&amp;nbsp;codes;&lt;/li&gt;
&lt;li&gt;wrote&amp;nbsp;issues;&lt;/li&gt;
&lt;li&gt;caught a&amp;nbsp;cold.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ADRs&lt;/h2&gt;
&lt;p&gt;I want to write a little about ADRs,
because I spent a non-trivial amount of time this week thinking about what they are and why we should write them.
You can find &lt;a href="https://github.com/bennettoxford/openprescribing-v2/blob/main/docs/architectural_decision_records.md"&gt;our definition and rationale&lt;/a&gt; in the codebase.
I&amp;#8217;m pleased that &lt;span class="caps"&gt;ADR&lt;/span&gt;-000 is self-exemplifying;
in other words,
the team&amp;#8217;s decision to record architectural decisions is captured by an &lt;span class="caps"&gt;ADR&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;If it&amp;#8217;s not clear,
then I&amp;#8217;m an advocate for writing ADRs.
Indeed, I&amp;#8217;m such an advocate that I made the team an offer:
When we make a decision, I will write the &lt;span class="caps"&gt;ADR&lt;/span&gt;.
The team accepted, although I&amp;#8217;m regretting that my offer didn&amp;#8217;t have an expiry&amp;nbsp;date.&lt;/p&gt;
&lt;p&gt;What I&amp;#8217;d like to focus on here is the questions software developers often ask about ADRs
and the reasons they often give for &lt;em&gt;not&lt;/em&gt; writing them.
First, some&amp;nbsp;questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What distinguishes architectural decisions from other decisions about a&amp;nbsp;codebase?&lt;/li&gt;
&lt;li&gt;How detailed should an &lt;span class="caps"&gt;ADR&lt;/span&gt;&amp;nbsp;be?&lt;/li&gt;
&lt;li&gt;How long should it take to write an &lt;span class="caps"&gt;ADR&lt;/span&gt;?&lt;/li&gt;
&lt;li&gt;When should I write an &lt;span class="caps"&gt;ADR&lt;/span&gt;?&lt;/li&gt;
&lt;li&gt;Is it okay to write an &lt;span class="caps"&gt;ADR&lt;/span&gt;&amp;nbsp;retrospectively?&lt;/li&gt;
&lt;li&gt;Is it okay to change an &lt;span class="caps"&gt;ADR&lt;/span&gt;, once it&amp;#8217;s&amp;nbsp;written?&lt;/li&gt;
&lt;li&gt;Do the benefits really outweigh the&amp;nbsp;costs?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And second, some&amp;nbsp;reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Information about code should live as close to the code as possible.
  ADRs are not close to the&amp;nbsp;code.&lt;/li&gt;
&lt;li&gt;Large organisations are advocates for writing ADRs,
  but that doesn&amp;#8217;t mean that small organisations should write them, too.
  Small organisations and large organisations are&amp;nbsp;different.&lt;/li&gt;
&lt;li&gt;Like Amazon, one of our &lt;a href="https://www.amazon.jobs/content/en/our-workplace/leadership-principles"&gt;Leadership Principles&lt;/a&gt; is Bias for Action.
  ADRs hinder this leadership&amp;nbsp;principle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I could reword the questions as reasons
(&amp;#8220;It takes too long to write ADRs&amp;#8221;),
but you know that&amp;nbsp;already.&lt;/p&gt;
&lt;p&gt;Alas, I don&amp;#8217;t have time to write more.
But something is better than&amp;nbsp;nothing.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I&amp;#8217;d like to thank Lucy, Peter, and Suzanne for their questions and comments about ADRs
last week and this&amp;nbsp;week.&lt;/p&gt;</content><category term="Weeknotes"/><category term="ADRs"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/01/09/weeknotes.html" rel="alternate"/><published>2026-01-09T00:00:00+00:00</published><updated>2026-01-09T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-01-09:/2026/01/09/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 9th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week, I was occupied by setting up the new team.
We&amp;#8217;re working on &lt;a href="https://openprescribing.net/"&gt;OpenPrescribing&lt;/a&gt;,
but as there&amp;#8217;s already a group of people who are associated with OpenPrescribing,&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;
and as that group of people refer to themselves as …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 9th January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;This week, I was occupied by setting up the new team.
We&amp;#8217;re working on &lt;a href="https://openprescribing.net/"&gt;OpenPrescribing&lt;/a&gt;,
but as there&amp;#8217;s already a group of people who are associated with OpenPrescribing,&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;
and as that group of people refer to themselves as a team,
calling the new team &amp;#8220;the OpenPrescribing team&amp;#8221; could be&amp;nbsp;confusing.&lt;/p&gt;
&lt;p&gt;A couple of candidates were
&amp;#8220;the OpenPrescribing delivery team&amp;#8221; and &amp;#8220;the OpenPrescribing development team&amp;#8221;.
Alas, &lt;em&gt;delivery&lt;/em&gt; means different things to different people:
people outside the new team will almost certainly be delivering OpenPrescribing in some way
and it would be unfair to suggest that our work delivered whereas their work didn&amp;#8217;t.
Neither candidate is consistent with the names of the other other tech group teams:
the Researcher Experience team, or &lt;span class="caps"&gt;REX&lt;/span&gt;;
the Reproducible Analytical Pipeline team, or &lt;span class="caps"&gt;RAP&lt;/span&gt;;
and the Research Software Innovation team, or &lt;span class="caps"&gt;RSI&lt;/span&gt;.
&lt;em&gt;Consistent&lt;/em&gt; is hardly well-defined:
&amp;#8220;about the thing, not the people&amp;#8221; and &amp;#8220;sounds like the name of a dinosaur, mostly&amp;#8221;
are probably what we mean by &lt;em&gt;consistent&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I asked my colleagues for their views and
&amp;#8220;sounds like the name of a dinosaur, mostly&amp;#8221; was as close to the consensus view as I could find.
There aren&amp;#8217;t any dinosaurs with &amp;#8220;prescribing&amp;#8221; or &amp;#8220;rx&amp;#8221;, meaning &lt;em&gt;prescription&lt;/em&gt;,
in their names, so we invented the &lt;em&gt;Prescribosaurus&lt;/em&gt;.
After some prompting by Thomas, an &lt;span class="caps"&gt;LLM&lt;/span&gt; generated the new team&amp;#8217;s&amp;nbsp;mascot.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The mascot of Team Prescribosaurus" src="https://www.dillingham.me.uk/images/prescribosaurus_small.png"&gt;&lt;/p&gt;
&lt;p&gt;Welcome, Team&amp;nbsp;Prescribosaurus!&lt;/p&gt;
&lt;p&gt;What else happened this&amp;nbsp;week?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;#8217;ve been reading &lt;a href="https://github.com/bennettoxford/openprescribing-v2/"&gt;the new codebase&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I had a lengthy discussion about supporting claims with&amp;nbsp;evidence.&lt;/li&gt;
&lt;li&gt;I had a lengthy discussion about Architectural Decision&amp;nbsp;Records.&lt;/li&gt;
&lt;li&gt;I learned about what front-end development looks like in&amp;nbsp;2026.&lt;/li&gt;
&lt;li&gt;Peter and I discussed what Team Prescribosaurus might &lt;a href="https://basecamp.com/shapeup/2.1-chapter-07"&gt;bet&lt;/a&gt; on next&amp;nbsp;week.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Jess suggested calling that group of people &amp;#8220;the OpenPrescribing network&amp;#8221;.
  I like the name, but it would take a lot of effort to socialise.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2026/01/02/weeknotes.html" rel="alternate"/><published>2026-01-02T00:00:00+00:00</published><updated>2026-01-02T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2026-01-02:/2026/01/02/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 2nd January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;After another hiatus, weeknotes are back.
A lot has happened in the last six months.
Nevertheless, these are &lt;em&gt;weeknotes&lt;/em&gt;.
What happened &lt;em&gt;this week&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been reading about
prescribing data, &lt;span class="caps"&gt;BNF&lt;/span&gt; codes, and dm+d codes
in preparation for starting work …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 2nd January&amp;nbsp;2026.&lt;/p&gt;
&lt;p&gt;After another hiatus, weeknotes are back.
A lot has happened in the last six months.
Nevertheless, these are &lt;em&gt;weeknotes&lt;/em&gt;.
What happened &lt;em&gt;this week&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been reading about
prescribing data, &lt;span class="caps"&gt;BNF&lt;/span&gt; codes, and dm+d codes
in preparation for starting work on &lt;a href="https://openprescribing.net/"&gt;OpenPrescribing&lt;/a&gt; next week.
We have a new team, &lt;a href="https://github.com/bennettoxford/openprescribing-v2/"&gt;a new codebase&lt;/a&gt;, a new GitHub project, and a new Slack&amp;nbsp;channel.&lt;/p&gt;
&lt;p&gt;I asked my colleagues what I should read to get up to speed and they&amp;nbsp;suggested:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.bennett.ox.ac.uk/blog/2018/11/limitations-of-nhs-england-prescribing-data/"&gt;Limitations of &lt;span class="caps"&gt;NHS&lt;/span&gt; England prescribing&amp;nbsp;data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bennett.ox.ac.uk/blog/2017/04/prescribing-data-bnf-codes/"&gt;Prescribing data: &lt;span class="caps"&gt;BNF&lt;/span&gt;&amp;nbsp;codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bennett.ox.ac.uk/blog/2019/08/what-is-the-dm-d-the-nhs-dictionary-of-medicines-and-devices/"&gt;What is the dm+d? The &lt;span class="caps"&gt;NHS&lt;/span&gt; Dictionary of Medicines and&amp;nbsp;Devices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These took me to many, many pages on various &lt;span class="caps"&gt;NHS&lt;/span&gt; websites.
The page I bookmarked, however, was &lt;a href="https://opendata.nhsbsa.net/dataset/english-prescribing-dataset-epd-with-snomed-code"&gt;English Prescribing Dataset (&lt;span class="caps"&gt;EPD&lt;/span&gt;) with &lt;span class="caps"&gt;SNOMED&lt;/span&gt; Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What have I learnt?
Well,
that an &lt;em&gt;&lt;a href="https://www.oxfordlearnersdictionaries.com/definition/english/indication?q=indication"&gt;indication&lt;/a&gt;&lt;/em&gt; is a symptom that suggests that particular medical treatment is necessary.
That prescribing data represent reimbursement claims from dispensing contractors;
prescriptions issued and prescriptions dispensed are separate, but related.
That &lt;span class="caps"&gt;BNF&lt;/span&gt; codes once formed a hierarchy; now they don&amp;#8217;t, unless you&amp;#8217;re the &lt;span class="caps"&gt;NHSBSA&lt;/span&gt;.
That a thing called ePACT2 gives authorised users access to prescribing data.
That ePACT2 relates to a thing called the One Drug Database.
That the dm+d contains an alphabet spaghetti of terms: &lt;span class="caps"&gt;VTM&lt;/span&gt;, &lt;span class="caps"&gt;VMP&lt;/span&gt;, &lt;span class="caps"&gt;VMPP&lt;/span&gt;, &lt;span class="caps"&gt;AMP&lt;/span&gt;, &lt;span class="caps"&gt;AMPP&lt;/span&gt;.
And that &lt;a href="https://bmjopen.bmj.com/content/8/2/e019643"&gt;my colleagues were helping the &lt;span class="caps"&gt;NHS&lt;/span&gt; identify cost savings over eight years ago&lt;/a&gt;.
Considerable cost savings:
a theoretical maximum of £410 million over 12&amp;nbsp;months.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/06/20/weeknotes.html" rel="alternate"/><published>2025-06-20T00:00:00+01:00</published><updated>2025-06-20T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-06-20:/2025/06/20/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been reading about &lt;a href="https://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt; (&lt;span class="caps"&gt;CI&lt;/span&gt;) and &lt;a href="https://martinfowler.com/bliki/ContinuousDelivery.html"&gt;continuous delivery&lt;/a&gt; (&lt;span class="caps"&gt;CD&lt;/span&gt;),
and trying to imagine software development without pull requests (PRs).
Although Ben &lt;span class="caps"&gt;B.C.&lt;/span&gt; has talked about this before,
my prompt was returning to a &lt;span class="caps"&gt;PR&lt;/span&gt; with unresolved comments …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been reading about &lt;a href="https://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt; (&lt;span class="caps"&gt;CI&lt;/span&gt;) and &lt;a href="https://martinfowler.com/bliki/ContinuousDelivery.html"&gt;continuous delivery&lt;/a&gt; (&lt;span class="caps"&gt;CD&lt;/span&gt;),
and trying to imagine software development without pull requests (PRs).
Although Ben &lt;span class="caps"&gt;B.C.&lt;/span&gt; has talked about this before,
my prompt was returning to a &lt;span class="caps"&gt;PR&lt;/span&gt; with unresolved comments.
It took me a non-trivial amount of time to remember the context
and I&amp;#8217;m sure it was no different for Alice,
who opened the &lt;span class="caps"&gt;PR&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The aspect of &lt;span class="caps"&gt;CI&lt;/span&gt;/&lt;span class="caps"&gt;CD&lt;/span&gt; I don&amp;#8217;t yet understand is how to break a feature into a logical sequence of commits,
&lt;em&gt;without first completing the feature&lt;/em&gt;.
I&amp;#8217;m used to creating the sequence by selectively staging and committing,
and to rearranging the sequence by rebasing before merging.
I&amp;#8217;m not used to merging a part-created sequence;
that is, to merging what Martin Fowler calls &lt;em&gt;latent code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/06/13/weeknotes.html" rel="alternate"/><published>2025-06-13T00:00:00+01:00</published><updated>2025-06-13T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-06-13:/2025/06/13/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://www.dillingham.me.uk/2025/06/06/weeknotes.html"&gt;last week&lt;/a&gt;,
additional paternity&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;This week I learnt about &lt;a href="https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---committer-date-is-author-date"&gt;&lt;code&gt;git rebase --committer-date-is-author-date&lt;/code&gt;&lt;/a&gt;.
Normally after a rebase,
the author date is that of the original commit
but the commit date is that of the new commit.
With this option,
the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;As &lt;a href="https://www.dillingham.me.uk/2025/06/06/weeknotes.html"&gt;last week&lt;/a&gt;,
additional paternity&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;This week I learnt about &lt;a href="https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---committer-date-is-author-date"&gt;&lt;code&gt;git rebase --committer-date-is-author-date&lt;/code&gt;&lt;/a&gt;.
Normally after a rebase,
the author date is that of the original commit
but the commit date is that of the new commit.
With this option,
the author date and the commit date are that of the original&amp;nbsp;commit.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been using this option to tidy up rebases,
such that the topological order of a set of commits is also the temporal order,
both by author date and commit date.
Honestly, I don&amp;#8217;t think a different temporal order matters that much
but &lt;a href="https://www.dillingham.me.uk/2025/05/30/weeknotes.html"&gt;as I&amp;#8217;ve said before&lt;/a&gt;,
&lt;a href="https://www.benkuhn.net/blub/"&gt;blub studies&lt;/a&gt; are&amp;nbsp;important!&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/06/06/weeknotes.html" rel="alternate"/><published>2025-06-06T00:00:00+01:00</published><updated>2025-06-06T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-06-06:/2025/06/06/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Paternity leave!
More specifically, &lt;em&gt;additional&lt;/em&gt; paternity&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hr.admin.ox.ac.uk/article/new-additional-paternity/partner-leave-launched"&gt;The University of Oxford Additional Paternity/Partner Leave&lt;/a&gt; scheme means I have 10 additional weeks of paternity leave.
Needless to say, the scheme is&amp;nbsp;amazing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.dillingham.me.uk/2025/05/30/weeknotes.html"&gt;Last week&lt;/a&gt;
I started thinking about pair programming as …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 6th June&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Paternity leave!
More specifically, &lt;em&gt;additional&lt;/em&gt; paternity&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hr.admin.ox.ac.uk/article/new-additional-paternity/partner-leave-launched"&gt;The University of Oxford Additional Paternity/Partner Leave&lt;/a&gt; scheme means I have 10 additional weeks of paternity leave.
Needless to say, the scheme is&amp;nbsp;amazing.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.dillingham.me.uk/2025/05/30/weeknotes.html"&gt;Last week&lt;/a&gt;
I started thinking about pair programming as an alternative to pull requests.
This week I read &amp;#8220;&lt;a href="https://martinfowler.com/articles/branching-patterns.html"&gt;Patterns for Managing Source Code Branches&lt;/a&gt;&amp;#8221; by Martin Fowler.
I&amp;#8217;d like to learn more about continuous delivery
and &amp;#8220;Patterns for Managing Source Code Branches&amp;#8221; gave useful and interesting&amp;nbsp;context.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>The victory of form over content</title><link href="https://www.dillingham.me.uk/2025/06/06/the-victory-of-form-over-content.html" rel="alternate"/><published>2025-06-06T00:00:00+01:00</published><updated>2025-06-06T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-06-06:/2025/06/06/the-victory-of-form-over-content.html</id><summary type="html">&lt;p&gt;You&amp;#8217;re a junior academic at a British university.
You know it&amp;#8217;s important to publish your research in high-impact journals.
You&amp;#8217;re already the first author on several papers.
But you&amp;#8217;re worried:
you need more.
And the journals aren&amp;#8217;t high-impact&amp;nbsp;enough.&lt;/p&gt;
&lt;p&gt;Someone from the university&amp;#8217;s Department …&lt;/p&gt;</summary><content type="html">&lt;p&gt;You&amp;#8217;re a junior academic at a British university.
You know it&amp;#8217;s important to publish your research in high-impact journals.
You&amp;#8217;re already the first author on several papers.
But you&amp;#8217;re worried:
you need more.
And the journals aren&amp;#8217;t high-impact&amp;nbsp;enough.&lt;/p&gt;
&lt;p&gt;Someone from the university&amp;#8217;s Department of People is organising a half-day workshop called
&amp;#8220;The hitchhiker&amp;#8217;s guide to getting your research published&amp;#8221;.
Other junior academics will discuss their perspectives on publishing their research.
A senior academic will give a short presentation.
It&amp;#8217;s just what you&amp;#8217;re looking&amp;nbsp;for!&lt;/p&gt;
&lt;p&gt;You arrive early.
There&amp;#8217;s tea and coffee.
Someone mentions pastries.
The senior academic gives a short presentation
&amp;#8212; more of an introduction, really &amp;#8212;
and departs,
muttering something about a committee.
You&amp;#8217;re put into a group with two other junior academics.
One is a historian.
You learn that historians don&amp;#8217;t publish papers in journals.
Instead, they publish books.
The other is a computer scientist.
You learn that computer scientists publish short papers in conference proceedings.
You&amp;#8217;ve been told that conference proceedings are low-impact,
but not in the fast-paced world of computer science,
where you learn that they&amp;#8217;re&amp;nbsp;high-impact.&lt;/p&gt;
&lt;p&gt;The three of you end up discussing
how much teaching you&amp;#8217;re doing,
how hard it is to find a parking space,
and how yeasty the beer is at the recently-opened micro-brewery.
When the person from the university&amp;#8217;s Department of People asks each group to report back,
the historian and the computer scientist look at you.
When it&amp;#8217;s your group&amp;#8217;s turn,
you say something vague about different disciplines having different norms
and make a joke about not needing a car parking space:
if you like a yeasty beer or two after a day spent teaching,
then it&amp;#8217;s better to take the bus&amp;nbsp;home.&lt;/p&gt;
&lt;p&gt;You promise to stay in touch with the historian and the computer scientist.
Whilst you&amp;#8217;re grateful for the coffee and the pastry,
you&amp;#8217;re left with the nagging feeling that you don&amp;#8217;t have much to show for your&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;You have experienced &lt;em&gt;the victory of form over content&lt;/em&gt;.&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s easy to spot form-over-content events.
Is the &lt;em&gt;form&lt;/em&gt;, or structure, of the event planned in advance?
Does it emphasise group work?
Is the content &lt;em&gt;not&lt;/em&gt; planned in advance?
Should it emerge from within the groups?
Are there several rounds of group work,
bookended by &amp;#8220;Opening remarks&amp;#8221; and &amp;#8220;Closing remarks&amp;#8221;?
If you answered &amp;#8220;Yes&amp;#8221; to these questions,
then you&amp;#8217;ve spotted a form-over-content&amp;nbsp;event.&lt;/p&gt;
&lt;p&gt;It isn&amp;#8217;t expensive to organise form-over-content events.
The organiser need only understand the structure,
and the structure of the event is the same as the structure of each round of group work:
someone says something to start;
people do something; and
someone says something to stop.
The organiser need not understand the content.
Indeed, the organiser need not have much
interaction with &lt;em&gt;anyone&lt;/em&gt; who understands the content in advance of the&amp;nbsp;event.&lt;/p&gt;
&lt;p&gt;Successful form-over-content events rely on the participants,
who should be able to compare their perspectives quickly and clearly.
If the event is about getting your research published,
then the participants should be able to compare their perspectives on,
for example, reading, writing, and note-taking strategies.
Ideally, the participants should have diverse perspectives,
both in kind and in degree.
In the previous example,
some participants should have well developed note-taking strategies
&amp;#8212; index cards, pin boards, a means of cross-referencing &amp;#8212;
others, less so.
Perhaps they have a stream-of-consciousness Google Doc,
into which they pour whatever they&amp;#8217;re thinking, whenever they&amp;#8217;re thinking&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;All this is to say that form-over-content events are more likely to benefit the organiser than the participants.
What to do?
As the organiser,
ask yourself what you can do to ensure the participants have diverse perspectives.
You could randomly assign participants to groups.
As a participant,
ask the organiser how the content should emerge from within the groups.
Who will report back?
Could the task of reporting back be rotated within each&amp;nbsp;group?&lt;/p&gt;
&lt;p&gt;Good&amp;nbsp;luck!&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;I didn&amp;#8217;t name &lt;em&gt;the victory of form over content&lt;/em&gt;;
my former colleague, &lt;a href="https://www.st-andrews.ac.uk/geography-sustainable-development/people/tas21"&gt;Dr Tim Stojanovic&lt;/a&gt;, did.
He must have mentioned it to me sometime between 2013 and 2014,
when I was a junior academic at the University of St Andrews.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Peter suggested that &lt;em&gt;the victory of form over content&lt;/em&gt; was synonymous with &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Surely_You%27re_Joking,_Mr._Feynman!#Cargo_Cult_Science"&gt;cargo cult science&lt;/a&gt;&lt;/em&gt;.
I&amp;#8217;m not sure.
Whilst the organisers of form-over-content events
&amp;#8220;focus on superficial aspects of a process without understanding the underlying principles&amp;#8221;,
the process (the form) and the underlying principles (the content) are unrelated.&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Essays"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/05/30/weeknotes.html" rel="alternate"/><published>2025-05-30T00:00:00+01:00</published><updated>2025-05-30T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-05-30:/2025/05/30/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 30th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;I updated my script for creating weeknotes.
It now creates an article for a given date, rather than for today&amp;#8217;s date,
which means I&amp;#8217;m less likely to run it on Friday and struggle to remember what I did that …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 30th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;I updated my script for creating weeknotes.
It now creates an article for a given date, rather than for today&amp;#8217;s date,
which means I&amp;#8217;m less likely to run it on Friday and struggle to remember what I did that week
(I&amp;#8217;m writing this on Wednesday!).
Expect longer, but not necessarily more interesting,&amp;nbsp;weeknotes.&lt;/p&gt;
&lt;p&gt;I read &amp;#8220;&lt;a href="https://martinfowler.com/articles/on-pair-programming.html"&gt;On Pair Programming&lt;/a&gt;&amp;#8221; by Birgitta Böckeler and Nina Siessegger.
The article describes how to pair,
the reasons why you should and shouldn&amp;#8217;t pair,
and concludes that you should pair judiciously.
It isn&amp;#8217;t a quick read
&amp;#8212; it&amp;#8217;s over 9,000 words long &amp;#8212;
but it&amp;#8217;s well-structured,
with clear headings and&amp;nbsp;sub-headings.&lt;/p&gt;
&lt;p&gt;I wasn&amp;#8217;t surprised by the article,
but I&amp;#8217;m keen on pairing.
It demonstrates to people who are less-than keen on pairing that well-respected people who work for well-respected organisations
have thought about the benefits and challenges of pairing,
and conclude that pairing (mostly)&amp;nbsp;works.&lt;/p&gt;
&lt;p&gt;Lucy recommended the article in Slack;
not to me specifically, but to the tech group in general.
Pairing isn&amp;#8217;t the &amp;#8220;sensible default&amp;#8221; in the tech group.
I&amp;#8217;m coming to the conclusion that it should&amp;nbsp;be.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been reading the &lt;a href="https://www.gnu.org/software/sed/manual/"&gt;sed&lt;/a&gt; and &lt;a href="https://www.gnu.org/software/grep/manual/"&gt;grep&lt;/a&gt; manuals (&lt;span class="caps"&gt;GNU&lt;/span&gt;).
I picked sed because I don&amp;#8217;t often use it outside Neovim
and even then in a very limited way&amp;nbsp;(&lt;code&gt;:%s/regexp/replacement/g&lt;/code&gt;).
I was curious about what I was missing.
I picked grep because I want to use it more, and more effectively:
I&amp;#8217;ve found it hard to learn on the job.
&lt;a href="https://www.benkuhn.net/blub/"&gt;Blub studies&lt;/a&gt; are&amp;nbsp;important!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Reflections on my first six months as a tech lead</title><link href="https://www.dillingham.me.uk/2025/05/25/reflections-on-my-first-six-months-as-a-tech-lead.html" rel="alternate"/><published>2025-05-25T00:00:00+01:00</published><updated>2025-05-25T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-05-25:/2025/05/25/reflections-on-my-first-six-months-as-a-tech-lead.html</id><summary type="html">&lt;p&gt;I became a tech lead in December 2024.
My team is small: just Alice, a junior developer, and me.
We were asked to work alongside researchers and health informaticians on the OpenPathology project
with the aim of designing, implementing, and evaluating dashboards.
Here, I&amp;#8217;d like to reflect on my …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I became a tech lead in December 2024.
My team is small: just Alice, a junior developer, and me.
We were asked to work alongside researchers and health informaticians on the OpenPathology project
with the aim of designing, implementing, and evaluating dashboards.
Here, I&amp;#8217;d like to reflect on my first six months as a tech lead,
rather than on the OpenPathology&amp;nbsp;project.&lt;/p&gt;
&lt;p&gt;What does the Bennett Institute expect of its tech leads?
We describe &lt;a href="https://gist.github.com/inglesp/ccfbe2f1c8480cd1717e37d07f560ed4#tech-lead"&gt;the role&lt;/a&gt; as about 80% leadership and about 20% hands-on engineering,
I haven&amp;#8217;t gone through my calendar,
but I feel that on average I&amp;#8217;ve spent about 40% of my time on leadership
and about 60% of my time on hands-on engineering, ±10%.
However, both my team and the project are small,
and my team isn&amp;#8217;t responsible for all aspects of the project;
just the tech&amp;nbsp;aspect.&lt;/p&gt;
&lt;p&gt;We describe leadership as a mix of three activities:
line management,
providing support (coaching, mentoring, training),
and owning the architectural direction of the &lt;a href="https://www.opensafely.org/"&gt;OpenSAFELY&lt;/a&gt; platform.
It&amp;#8217;s structured around three weekly&amp;nbsp;meetings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a one-to-one with Alice (about 30&amp;nbsp;minutes)&lt;/li&gt;
&lt;li&gt;a tactical meeting with the other tech leads (about 40&amp;nbsp;minutes)&lt;/li&gt;
&lt;li&gt;a strategic meeting with the other tech leads (about 40&amp;nbsp;minutes)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was apprehensive about line management;
thoughts of filling in Word forms and approving annual leave depressed me.
For the most part, though, line management has been straightforward.
There &lt;em&gt;are&lt;/em&gt; Word forms to fill in and there &lt;em&gt;is&lt;/em&gt; annual leave to approve,
but I&amp;#8217;ve found I can manage the former by blocking out time in my calendar
(and forgetting about the Word forms until the blocked out time arrives).
Similarly, managing the latter means clicking &amp;#8220;Approve&amp;#8221; every so often.
Hardly&amp;nbsp;onerous!&lt;/p&gt;
&lt;p&gt;The leadership activity I&amp;#8217;ve found most rewarding is providing support.
I was Katie&amp;#8217;s buddy &lt;a href="https://www.dillingham.me.uk/2024/09/13/weeknotes.html"&gt;from last September&lt;/a&gt; to this January
and I enjoyed helping her become an effective junior developer.
Being a buddy and being a tech lead are different;
I have more direct influence over Alice&amp;#8217;s career progression than I had over Katie&amp;#8217;s, for example.
However, providing support is common to both roles and I&amp;#8217;m enjoying helping Alice just as much as I enjoyed helping Katie.
Answering questions about our systems and processes, and
having to think about how I know what I know, or whether I actually know it,
has helped me reason more effectively.
We&amp;#8217;ve also taken some useful and interesting deep-dives that I wouldn&amp;#8217;t have taken otherwise:
nginx configuration and&amp;nbsp;Django&amp;#8217;s &lt;code&gt;AppConfig&lt;/code&gt; with Katie;
&lt;a href="https://just.systems/man/en/shebang-recipes.html"&gt;just shebang recipes&lt;/a&gt; and &lt;a href="https://python-patterns.guide/"&gt;Python design patterns&lt;/a&gt; with&amp;nbsp;Alice.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t think I&amp;#8217;ve fully taken ownership of the architectural direction of the OpenSAFELY platform,
although I am writing a proposal for a feature that will touch several of our systems and processes.
Writing a proposal is hard,
and there always seem to be more &lt;a href="https://untools.co/eisenhower-matrix/"&gt;important and urgent&lt;/a&gt; things to do.
Maybe the things &lt;em&gt;are&lt;/em&gt; important but &lt;em&gt;aren&amp;#8217;t&lt;/em&gt; urgent,
so I should schedule them rather then do them?
If I did, then my leadership/hands-on engineering split would move from 40/60 to&amp;nbsp;80/20.&lt;/p&gt;
&lt;p&gt;Project management doesn&amp;#8217;t fit into any of the leadership activities.
I&amp;#8217;ve found it rewarding, nonetheless.
Writing good issues, like all writing, is a skill.
There are more opportunities to practice this skill as a tech lead than as a senior developer
(&lt;em&gt;someone&lt;/em&gt; has to write the issues, after all!).
There&amp;#8217;s also something about setting up a Kanban-style board
and watching the issues move across it from left-to-right that I find&amp;nbsp;rewarding.&lt;/p&gt;
&lt;p&gt;To summarise:
providing support and project management are rewarding;
line management isn&amp;#8217;t nearly as onerous as expected;
and taking ownership of the architectural direction of the OpenSAFELY platform needs more&amp;nbsp;work.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Essays"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/05/23/weeknotes.html" rel="alternate"/><published>2025-05-23T00:00:00+01:00</published><updated>2025-05-23T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-05-23:/2025/05/23/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 23rd May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Katie showed me &lt;a href="https://github.com/pytest-dev/pytest-django/blob/5ada9c1596ee9e0624801d553995d98d2e3ccce8/pytest_django/fixtures.py#L583"&gt;a code snippet&lt;/a&gt; within which I noticed the following&amp;nbsp;idiom:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;a_list&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I was sure&amp;nbsp;that &lt;code&gt;[:]&lt;/code&gt; copied the list,
but I wasn&amp;#8217;t sure&amp;nbsp;what &lt;code&gt;del&lt;/code&gt; did to it.
Deleted a copy of the list?
Deleted the contents …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 23rd May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Katie showed me &lt;a href="https://github.com/pytest-dev/pytest-django/blob/5ada9c1596ee9e0624801d553995d98d2e3ccce8/pytest_django/fixtures.py#L583"&gt;a code snippet&lt;/a&gt; within which I noticed the following&amp;nbsp;idiom:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;a_list&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I was sure&amp;nbsp;that &lt;code&gt;[:]&lt;/code&gt; copied the list,
but I wasn&amp;#8217;t sure&amp;nbsp;what &lt;code&gt;del&lt;/code&gt; did to it.
Deleted a copy of the list?
Deleted the contents of a copy of the list?
What happened to the&amp;nbsp;list?&lt;/p&gt;
&lt;p&gt;After experimenting in the Python shell,
I realised&amp;nbsp;that &lt;code&gt;del&lt;/code&gt; and &lt;code&gt;[:]&lt;/code&gt; deleted the contents of the list.
In other words, they&amp;#8217;re equivalent to the&amp;nbsp;following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;a_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I find the use&amp;nbsp;of &lt;code&gt;del&lt;/code&gt; and &lt;code&gt;[:]&lt;/code&gt; confusing.
If you slice a list, then you get a new list.
But if you delete a slice of a list,
then you don&amp;#8217;t:
the elements contained by the slice are deleted from the&amp;nbsp;list.&lt;/p&gt;
&lt;p&gt;When we describe code as &amp;#8220;idiomatic&amp;#8221;,
we mean &amp;#8220;a characteristic mode of expression&amp;#8221; (Oxford Languages).
In this case, however,
I mean &amp;#8220;a group of words established by usage as having a meaning not deducible from those of individual words&amp;#8221; (Oxford&amp;nbsp;Languages).&lt;/p&gt;
&lt;p&gt;This week,
I also finished writing a proposal for a feature that will touch several of our systems and processes;
talked about the future of the OpenPathology project;
and helped Alice update &lt;a href="https://docs.opensafely.org/case-control-studies/"&gt;the case-control studies documentation&lt;/a&gt;.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/05/16/weeknotes.html" rel="alternate"/><published>2025-05-16T00:00:00+01:00</published><updated>2025-05-16T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-05-16:/2025/05/16/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 16th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Annual&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;For several reasons I found myself going to bed and waking up early.
I started reading about &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; (it&amp;#8217;s a programming language, dad)
and working through the &lt;a href="https://doc.rust-lang.org/book/ch01-00-getting-started.html"&gt;Getting Started&lt;/a&gt; section of &lt;a href="https://doc.rust-lang.org/book/"&gt;The Book&lt;/a&gt;.
I was impressed by the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 16th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;Annual&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;For several reasons I found myself going to bed and waking up early.
I started reading about &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; (it&amp;#8217;s a programming language, dad)
and working through the &lt;a href="https://doc.rust-lang.org/book/ch01-00-getting-started.html"&gt;Getting Started&lt;/a&gt; section of &lt;a href="https://doc.rust-lang.org/book/"&gt;The Book&lt;/a&gt;.
I was impressed by the quality of the documentation
and the friendliness of the community.
I should make time to learn Rust&amp;nbsp;properly.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2025/05/09/weeknotes.html" rel="alternate"/><published>2025-05-09T00:00:00+01:00</published><updated>2025-05-09T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2025-05-09:/2025/05/09/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 9th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;After a hiatus, weeknotes are (hopefully) back.
In the last six months, I&amp;#8217;ve become a dad, taken a month off, and become a tech lead.
Nevertheless, these are &lt;em&gt;weeknotes&lt;/em&gt;.
What happened &lt;em&gt;this week&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Several things happened this week,
but I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 9th May&amp;nbsp;2025.&lt;/p&gt;
&lt;p&gt;After a hiatus, weeknotes are (hopefully) back.
In the last six months, I&amp;#8217;ve become a dad, taken a month off, and become a tech lead.
Nevertheless, these are &lt;em&gt;weeknotes&lt;/em&gt;.
What happened &lt;em&gt;this week&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Several things happened this week,
but I only have time to write about one:
I was frustrated by an idea that I keep hearing at work.
Namely, that you need a copy of production data for local development.
Or, if you&amp;#8217;re not using a copy of production data when you&amp;#8217;re doing local development,
then you&amp;#8217;re not doing local development&amp;nbsp;right.&lt;/p&gt;
&lt;p&gt;Certainly, it&amp;#8217;s handy to tinker with a copy of production data;
you can tailor a user interface to fit a long string
or to fit domain-specific words and expressions (&amp;#8220;jargon&amp;#8221;).
Having a copy of production data also makes replicating bugs easier.
However, production data can be large.
They can also contain &lt;a href="https://en.wikipedia.org/wiki/Personal_data"&gt;personal data&lt;/a&gt;,
which must be removed before a copy is made.
And once the personal data are removed,
the copy is no longer a copy of production&amp;nbsp;data.&lt;/p&gt;
&lt;p&gt;Time&amp;#8217;s&amp;nbsp;up!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/11/08/weeknotes.html" rel="alternate"/><published>2024-11-08T00:00:00+00:00</published><updated>2024-11-08T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-11-08:/2024/11/08/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 8th November&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;I wrote these on Monday, 11th November.
I struggled to remember the previous&amp;nbsp;week!&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;REX&lt;/span&gt; (Researcher EXperience) team started a new initiative:
&amp;#8220;Onboarding OpenCodelists&amp;#8221;.
Lucy and Mary asked us to split into two squads.
One squad will focus on maintaining …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 8th November&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;I wrote these on Monday, 11th November.
I struggled to remember the previous&amp;nbsp;week!&lt;/p&gt;
&lt;p&gt;The &lt;span class="caps"&gt;REX&lt;/span&gt; (Researcher EXperience) team started a new initiative:
&amp;#8220;Onboarding OpenCodelists&amp;#8221;.
Lucy and Mary asked us to split into two squads.
One squad will focus on maintaining OpenCodelists;
the other squad will focus on&amp;nbsp;discovery.&lt;/p&gt;
&lt;p&gt;From my perspective,
maintaining OpenCodelists is important;
discovery, less so.
It&amp;#8217;s not clear to me what happens after discovery,
because the initiative doesn&amp;#8217;t seem to allocate any time for developing new features.
Lucy also said that she wasn&amp;#8217;t clear whether the &lt;span class="caps"&gt;REX&lt;/span&gt; team would be responsible for OpenCodelists for much&amp;nbsp;longer.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/11/01/weeknotes.html" rel="alternate"/><published>2024-11-01T00:00:00+00:00</published><updated>2024-11-01T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-11-01:/2024/11/01/weeknotes.html</id><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 1st November&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;Annual&amp;nbsp;leave!&lt;/p&gt;
&lt;p&gt;We went to on holiday.
Some walking, some paddleboarding, some&amp;nbsp;running.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/10/18/weeknotes.html" rel="alternate"/><published>2024-10-18T00:00:00+01:00</published><updated>2024-10-18T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-10-18:/2024/10/18/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 18th October&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m back after a two-week&amp;nbsp;hiatus.&lt;/p&gt;
&lt;p&gt;Katie and I have reduced the frequency of our meetings,
which I think has helped each of us focus on our other tasks.
We&amp;#8217;re now meeting on Monday, Wednesday, and Friday mornings for …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 18th October&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m back after a two-week&amp;nbsp;hiatus.&lt;/p&gt;
&lt;p&gt;Katie and I have reduced the frequency of our meetings,
which I think has helped each of us focus on our other tasks.
We&amp;#8217;re now meeting on Monday, Wednesday, and Friday mornings for a &amp;#8220;short&amp;#8221; hour
and Monday to Friday afternoons for a &amp;#8220;short&amp;#8221; half&amp;nbsp;hour.&lt;/p&gt;
&lt;p&gt;We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Types of test (&lt;span class="caps"&gt;MDN&lt;/span&gt;&amp;#8217;s &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Testing"&gt;Django Tutorial&lt;/a&gt; lists&amp;nbsp;16!)&lt;/li&gt;
&lt;li&gt;Variable&amp;nbsp;scope&lt;/li&gt;
&lt;li&gt;Closures&lt;/li&gt;
&lt;li&gt;&lt;a href="https://xkcd.com/356/"&gt;Nerd&amp;nbsp;sniping&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also took a &lt;a href="https://youtu.be/5VZrCnKLmP8"&gt;code walk&lt;/a&gt; through job-server.
Katie and I reviewed an excellent pull request from Mike,
and Katie reviewed a small (also excellent) pull request (also from Mike) on her&amp;nbsp;own.&lt;/p&gt;
&lt;p&gt;Besides buddying,
I was on tech support.
Like last time, it was great to be busy again.
Lucy was away, so I took over her non-line management tasks.
With buddying, tech support, and non-line management tasks,
there wasn&amp;#8217;t much time&amp;nbsp;left.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/09/27/weeknotes.html" rel="alternate"/><published>2024-09-27T00:00:00+01:00</published><updated>2024-09-27T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-09-27:/2024/09/27/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 27th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my third full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/5.1/ref/models/querysets/#when-querysets-are-evaluated"&gt;When &lt;code&gt;QuerySet&lt;/code&gt;s are&amp;nbsp;evaluated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The nature of the &lt;span class="caps"&gt;SQL&lt;/span&gt; statements generated by Django&amp;#8217;s &lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;List comprehensions&amp;nbsp;(listcomps)&lt;/li&gt;
&lt;li&gt;Breakpoints, &lt;a href="https://docs.python.org/3.12/library/pdb.html#module-pdb"&gt;the Python debugger&lt;/a&gt;, and &lt;a href="https://github.com/pdbpp/pdbpp"&gt;pdb++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://django-debug-toolbar.readthedocs.io/"&gt;Django Debug&amp;nbsp;Toolbar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Django …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 27th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my third full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.djangoproject.com/en/5.1/ref/models/querysets/#when-querysets-are-evaluated"&gt;When &lt;code&gt;QuerySet&lt;/code&gt;s are&amp;nbsp;evaluated&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The nature of the &lt;span class="caps"&gt;SQL&lt;/span&gt; statements generated by Django&amp;#8217;s &lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;List comprehensions&amp;nbsp;(listcomps)&lt;/li&gt;
&lt;li&gt;Breakpoints, &lt;a href="https://docs.python.org/3.12/library/pdb.html#module-pdb"&gt;the Python debugger&lt;/a&gt;, and &lt;a href="https://github.com/pdbpp/pdbpp"&gt;pdb++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://django-debug-toolbar.readthedocs.io/"&gt;Django Debug&amp;nbsp;Toolbar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Django&amp;#8217;s requests, responses, and middleware (within the context of views and&amp;nbsp;authentication)&lt;/li&gt;
&lt;li&gt;Callables (within the context of a&amp;nbsp;URLconf)&lt;/li&gt;
&lt;li&gt;And &lt;a href="https://draculatheme.com/"&gt;Dracula&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Katie also started &lt;span class="caps"&gt;MDN&lt;/span&gt;&amp;#8217;s &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website"&gt;Django Tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There were many great learning moments with Katie this week.
The best?
On Monday, I watched Katie find out&amp;nbsp;that &lt;code&gt;MyModel.objects.count()&lt;/code&gt; caches the result.
On Friday, I heard Katie ask
&amp;#8220;Why does this view take less time to render, when I refresh the page?&amp;#8221;
and immediately answer &amp;#8220;Ah, because the results are&amp;nbsp;cached!&amp;#8221;&lt;/p&gt;
&lt;p&gt;Besides buddying,
I was on tech support this week.
It was great to be busy again, after several months of quiet.
I revisited how we restrict access to datasets,
and had a couple of productive conversations with Lucy and Ben &lt;span class="caps"&gt;B.C.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Finally, Simon reminded me of &amp;#8220;&lt;a href="https://hypermedia.systems/"&gt;Hypermedia Systems&lt;/a&gt;&amp;#8221;.
I&amp;#8217;m really enjoying it.
If nothing else, then it&amp;#8217;s helping me understand why I have an aversion to&amp;nbsp;SPAs.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/09/20/weeknotes.html" rel="alternate"/><published>2024-09-20T00:00:00+01:00</published><updated>2024-09-20T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-09-20:/2024/09/20/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my second full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Django shell&amp;nbsp;(&lt;code&gt;manage.py shell&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;the database shell&amp;nbsp;(&lt;code&gt;manage.py dbshell&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;displaying two shells in one window with &lt;a href="https://gnome-terminator.org/"&gt;Terminator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;creating and saving models with managers and&amp;nbsp;instances&lt;/li&gt;
&lt;li&gt;environment …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 20th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my second full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Django shell&amp;nbsp;(&lt;code&gt;manage.py shell&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;the database shell&amp;nbsp;(&lt;code&gt;manage.py dbshell&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;displaying two shells in one window with &lt;a href="https://gnome-terminator.org/"&gt;Terminator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;creating and saving models with managers and&amp;nbsp;instances&lt;/li&gt;
&lt;li&gt;environment variables and their use in the &lt;a href="https://12factor.net/"&gt;twelve-factor app&amp;nbsp;methodology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;file&amp;nbsp;permissions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I gave an hour-long talk on &amp;#8220;Writing and running study code&amp;#8221;,
a 10 minute talk on job-server,
and another 10 minute talk on the OpenSAFELY command-line&amp;nbsp;interface.&lt;/p&gt;
&lt;p&gt;I revisited how the OpenSAFELY platform restricts datasets,
tracing a line from the OpenSAFELY command-line interface to GitHub issues,
via research-template and research-action.
I&amp;#8217;m hoping to discuss how the OpenSAFELY platform restricts datasets in next week&amp;#8217;s &amp;#8220;Cabinet of&amp;nbsp;Curiosities&amp;#8221;.&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Weeknotes</title><link href="https://www.dillingham.me.uk/2024/09/13/weeknotes.html" rel="alternate"/><published>2024-09-13T00:00:00+01:00</published><updated>2024-09-13T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2024-09-13:/2024/09/13/weeknotes.html</id><summary type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my first full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;setting up a &lt;span class="caps"&gt;GPG&lt;/span&gt;&amp;nbsp;key&lt;/li&gt;
&lt;li&gt;the differences between a &lt;span class="caps"&gt;GPG&lt;/span&gt; key and an &lt;span class="caps"&gt;SSH&lt;/span&gt;&amp;nbsp;key&lt;/li&gt;
&lt;li&gt;signing&amp;nbsp;commits&lt;/li&gt;
&lt;li&gt;the pros and cons of &lt;span class="caps"&gt;HTTP&lt;/span&gt; and &lt;span class="caps"&gt;SSH&lt;/span&gt; for communicating with a …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Weeknotes for the week finishing Friday, 13th September&amp;nbsp;2024.&lt;/p&gt;
&lt;p&gt;This was my first full week as Katie&amp;#8217;s buddy.
We&amp;nbsp;covered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;setting up a &lt;span class="caps"&gt;GPG&lt;/span&gt;&amp;nbsp;key&lt;/li&gt;
&lt;li&gt;the differences between a &lt;span class="caps"&gt;GPG&lt;/span&gt; key and an &lt;span class="caps"&gt;SSH&lt;/span&gt;&amp;nbsp;key&lt;/li&gt;
&lt;li&gt;signing&amp;nbsp;commits&lt;/li&gt;
&lt;li&gt;the pros and cons of &lt;span class="caps"&gt;HTTP&lt;/span&gt; and &lt;span class="caps"&gt;SSH&lt;/span&gt; for communicating with a remote&amp;nbsp;repository&lt;/li&gt;
&lt;li&gt;a couple of useful key bindings; &lt;kbd&gt;Ctrl-l&lt;/kbd&gt; (clear screen) and &lt;kbd&gt;Ctrl-r&lt;/kbd&gt; (reverse search&amp;nbsp;history)&lt;/li&gt;
&lt;li&gt;piping&amp;nbsp;to &lt;code&gt;xclip&lt;/code&gt; (not bad for week&amp;nbsp;one!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I was pleased we talked about empirical method (&amp;#8220;hypothesis-driven development&amp;#8221;).
Katie seemed to embrace it!
We used it to test that Katie could sign her commits,
although this took longer than it should have taken because I misunderstood GitHub&amp;#8217;s &lt;span class="caps"&gt;UI&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;I decided to learn more about &lt;a href="https://jonas.github.io/tig/"&gt;Tig&lt;/a&gt; this week.
I got confused, because Tig wasn&amp;#8217;t doing what I wanted it to do.
But then I realised that I was thinking of it as a tool you open once per session,
when I should have been thinking of it as tool you open many times per session,
once for each task.
I set up a couple of useful key bindings,&amp;nbsp;nonetheless.&lt;/p&gt;
&lt;p&gt;Getting confused prompted me to learn more about &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection"&gt;revision selection&lt;/a&gt;
and to find a well-hidden page in the Git docs called &amp;#8220;&lt;a href="https://git-scm.com/docs/gitrevisions"&gt;gitrevisions&lt;/a&gt;&amp;#8221;.
&lt;code&gt;^&lt;/code&gt; and &lt;code&gt;~&lt;/code&gt; started to make more sense, which&amp;nbsp;meant &lt;code&gt;git log&lt;/code&gt; started to make more sense&amp;nbsp;too.&lt;/p&gt;
&lt;p&gt;Finally, I learnt more about Git internals (Chapter 10 of &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git&lt;/a&gt;).
Understanding
&lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-References"&gt;Git references&lt;/a&gt;
better helped me work out&amp;nbsp;why &lt;code&gt;git branch&lt;/code&gt; didn&amp;#8217;t report the branch name,&amp;nbsp;but &lt;code&gt;git status&lt;/code&gt; did, for a newly-initialised repository.
Katie spotted the discrepancy when we were testing that she could sign her commits.
Thanks,&amp;nbsp;Katie!&lt;/p&gt;</content><category term="Weeknotes"/></entry><entry><title>Less neat, less tidy, and more unpredictable: Improving your code with property-based tests</title><link href="https://www.dillingham.me.uk/2023/10/18/property-based-tests.html" rel="alternate"/><published>2023-10-18T00:00:00+01:00</published><updated>2023-10-18T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2023-10-18:/2023/10/18/property-based-tests.html</id><summary type="html">&lt;p&gt;I gave a talk today at the &lt;a href="https://nhsrcommunity.com/"&gt;&lt;span class="caps"&gt;NHS&lt;/span&gt;-R&lt;/a&gt; conference.
It was called &lt;em&gt;Less neat, less tidy, and more unpredictable: Improving your code with property-based tests&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;As conscientious data scientists,
we know that it&amp;#8217;s good practice to write unit tests to check that our code is working correctly …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I gave a talk today at the &lt;a href="https://nhsrcommunity.com/"&gt;&lt;span class="caps"&gt;NHS&lt;/span&gt;-R&lt;/a&gt; conference.
It was called &lt;em&gt;Less neat, less tidy, and more unpredictable: Improving your code with property-based tests&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;As conscientious data scientists,
we know that it&amp;#8217;s good practice to write unit tests to check that our code is working correctly.
However, unit tests cover single scenarios and, despite our best intentions,
these scenarios are often far neater, far tidier, and far more predictable than those we encounter in the&amp;nbsp;wild.&lt;/p&gt;
&lt;p&gt;How can we cover less neat, less tidy, and more unpredictable scenarios?
One answer is to complement unit tests with property-based, or generative, tests.
Popularised by Haskell&amp;#8217;s Quickcheck library,
property-based tests can cover tens, hundreds, or even thousands of disparate scenarios
by generating large amounts of input data to match a specification,
and by checking that the results of operating on these data are consistent with one or more guarantees.
As conscientious data scientists,
our job becomes one of carefully crafting the specifications and guarantees,
rather than one of carefully crafting the input&amp;nbsp;data.&lt;/p&gt;
&lt;p&gt;In this talk, I&amp;#8217;ll introduce property-based tests with examples in Python and R.
I&amp;#8217;ll also discuss how to switch from thinking about input data to thinking about specifications and guarantees.
Finally, I&amp;#8217;ll describe how we use property-based tests in our work at the Bennett Institute for Applied Data Science
to improve our research and to improve ehrQL, the Electronic Health Records Query&amp;nbsp;Language.&lt;/p&gt;</content><category term="Talks"/><category term="property-based-tests"/><category term="ehrQL"/></entry><entry><title>Code Reuse in a Trusted Research Environment</title><link href="https://www.dillingham.me.uk/2022/11/16/code-reuse-trusted-research-environment.html" rel="alternate"/><published>2022-11-16T00:00:00+00:00</published><updated>2022-11-16T00:00:00+00:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2022-11-16:/2022/11/16/code-reuse-trusted-research-environment.html</id><summary type="html">&lt;p&gt;I gave a talk today at the &lt;a href="https://nhsrcommunity.com/"&gt;&lt;span class="caps"&gt;NHS&lt;/span&gt;-R&lt;/a&gt; conference.
It was called &lt;em&gt;Code Reuse in a Trusted Research Environment: Reusable Actions in OpenSAFELY&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;OpenSAFELY is a secure, transparent, open-source software platform for analysis of electronic health records data.
It can be deployed to create a Trusted Research Environment …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I gave a talk today at the &lt;a href="https://nhsrcommunity.com/"&gt;&lt;span class="caps"&gt;NHS&lt;/span&gt;-R&lt;/a&gt; conference.
It was called &lt;em&gt;Code Reuse in a Trusted Research Environment: Reusable Actions in OpenSAFELY&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;OpenSAFELY is a secure, transparent, open-source software platform for analysis of electronic health records data.
It can be deployed to create a Trusted Research Environment (&lt;span class="caps"&gt;TRE&lt;/span&gt;) or, alternatively, as a privacy-enhancing layer on any existing &lt;span class="caps"&gt;TRE&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;When undertaking a project within OpenSAFELY, a researcher will typically write one or more scripted actions;
logical units of analytic Python, R, or Stata code.
However, to encourage the development of well-tested, well-documented code that can be shared between projects, OpenSAFELY supports reusable&amp;nbsp;actions.&lt;/p&gt;
&lt;p&gt;Reusable actions are similar to packages in Python or R:
versioned collections of analytic code, tests, and documentation that can be made available to other researchers via &lt;a href="https://actions.opensafely.org/"&gt;https://actions.opensafely.org/&lt;/a&gt;, the OpenSAFELY equivalent of PyPI or &lt;span class="caps"&gt;CRAN&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In this talk, I will discuss the challenges of code reuse within a &lt;span class="caps"&gt;TRE&lt;/span&gt;.
I will then discuss how reusable actions in OpenSAFELY overcome these challenges,
situating reusable actions within OpenSAFELY&amp;#8217;s strict security&amp;nbsp;protocols.&lt;/p&gt;
&lt;p&gt;I will describe the structure of an OpenSAFELY project,
and how a researcher can convert a scripted action, which promotes reusing code within a project;
to a reusable action, which promotes sharing code between projects.
Although I will give an example in Python, the same principles apply to R or Stata.
Finally, I will survey the landscape of existing reusable actions, from the vantage point of &lt;a href="https://actions.opensafely.org/"&gt;https://actions.opensafely.org/&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What is&amp;nbsp;OpenSAFELY?&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.opensafely.org/"&gt;OpenSAFELY&lt;/a&gt; is a secure, transparent, open-source software platform for analysis of electronic health records&amp;nbsp;data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It can be deployed to&amp;nbsp;create&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;span class="caps"&gt;TRE&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;a privacy-enhancing layer on an existing &lt;span class="caps"&gt;TRE&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why reuse&amp;nbsp;code?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Avoid duplicating identical lines of code in different locations (e.g. by&amp;nbsp;copying-and-pasting)&lt;/li&gt;
&lt;li&gt;Instead, use the same lines of code in each&amp;nbsp;location&lt;/li&gt;
&lt;li&gt;Over time, improve the functionality that those lines of code&amp;nbsp;implement&lt;/li&gt;
&lt;li&gt;Tests&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Bugs&lt;/li&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Do this within, as well as between,&amp;nbsp;projects&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Code reuse in&amp;nbsp;practice&lt;/h2&gt;
&lt;p&gt;Code reuse within a&amp;nbsp;project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Factor code into functions, classes,&amp;nbsp;methods&lt;/li&gt;
&lt;li&gt;Factor these into modules or&amp;nbsp;packages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Code reuse between&amp;nbsp;projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Release these to software repositories, such as PyPI or &lt;span class="caps"&gt;CRAN&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;TREs and code reuse: some&amp;nbsp;challenges&lt;/h2&gt;
&lt;h3&gt;Skills&amp;nbsp;challenges&lt;/h3&gt;
&lt;p&gt;Releasing code requires a different set of skills to writing&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;We need to make&amp;nbsp;choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tooling (Flit, Poetry,&amp;nbsp;Setuptools)&lt;/li&gt;
&lt;li&gt;Versions of our chosen programming language (3.8, 3.9,&amp;nbsp;3.10)&lt;/li&gt;
&lt;li&gt;Operating systems (Unix-like,&amp;nbsp;Windows)&lt;/li&gt;
&lt;li&gt;Versioning scheme (SemVer,&amp;nbsp;CalVer)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Security&amp;nbsp;challenges&lt;/h3&gt;
&lt;p&gt;You may be familiar with&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip install matplotlib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;conda install matplotlib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ggplot2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In each case we&amp;#8217;re downloading a package from the Internet to a computer.
What if the computer is within a &lt;span class="caps"&gt;TRE&lt;/span&gt;?&lt;/p&gt;
&lt;p&gt;If packages can be downloaded, then can data be uploaded?&lt;br&gt;
→ TREs probably shouldn&amp;#8217;t have unrestricted access to the&amp;nbsp;Internet&lt;/p&gt;
&lt;p&gt;Where are packages hosted? Which software repository? Which mirror?&lt;br&gt;
Software repositories and mirrors can be compromised.&lt;br&gt;
→ TREs probably shouldn&amp;#8217;t have unrestricted access to software repositories and&amp;nbsp;mirrors.&lt;/p&gt;
&lt;p&gt;Did we get the package we asked for?&lt;br&gt;
Packages can be compromised.&lt;br&gt;
→ TREs probably shouldn&amp;#8217;t have unrestricted access to&amp;nbsp;packages.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The skills and security challenges can be addressed,
but they distract us from achieving our&amp;nbsp;aims:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid duplicating identical lines of code in different&amp;nbsp;locations&lt;/li&gt;
&lt;li&gt;Instead, use the same lines of code in each&amp;nbsp;location&lt;/li&gt;
&lt;li&gt;Over time, improve the functionality that those lines of code&amp;nbsp;implement&lt;/li&gt;
&lt;li&gt;Do this within, as well as between,&amp;nbsp;projects&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What are scripted&amp;nbsp;actions?&lt;/h2&gt;
&lt;p&gt;An OpenSAFELY project is a set of steps, which when run, produce a result.
We call each step an &lt;em&gt;action&lt;/em&gt;.
Each action is run within a Docker container, which doesn&amp;#8217;t have access to the&amp;nbsp;Internet.&lt;/p&gt;
&lt;p&gt;Some actions address specific tasks:
a cohort-extractor action, for example, allows a researcher to extract a&amp;nbsp;cohort.&lt;/p&gt;
&lt;p&gt;The researcher analyses the cohort by writing one or more &lt;em&gt;scripted actions&lt;/em&gt; in Python, R, or Stata.
For example, the researcher may write a scripted action to round counts in a contingency table to the nearest&amp;nbsp;seven.&lt;/p&gt;
&lt;p&gt;Scripted actions help us achieve our aims, in part, but they are project-specific:
we achieve code reuse within a project, but not between&amp;nbsp;projects.&lt;/p&gt;
&lt;h2&gt;What are reusable&amp;nbsp;actions?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Reusable actions&lt;/em&gt; are scripted actions that have been decoupled from their projects.
They help us achieve code reuse within, as well as between,&amp;nbsp;projects.&lt;/p&gt;
&lt;p&gt;Whilst we could think of reusable actions as packages,
it&amp;#8217;s better to think of them as reusable&amp;nbsp;projects.&lt;/p&gt;
&lt;h2&gt;From scripted to&amp;nbsp;reusable&lt;/h2&gt;
&lt;h3&gt;First step:&amp;nbsp;refactoring&lt;/h3&gt;
&lt;p&gt;Typically, project-specific information is hard-coded in a scripted action.
For example, we may hard-code the location of an input file like&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;path_to_input_file = &amp;quot;data/input.csv&amp;quot;

def my_function():
    my_other_function(path_to_input_file)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which we may run like&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python my_scripted_action.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In a reusable action, project-specific information is passed as arguments to a command-line interface.
For example, we may rewrite our scripted action as a reusable action like&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;def my_function():
    parser = ArgumentParser()
    parser.add_argument(&amp;quot;--path-to-input-file&amp;quot;)
    args = parser.parse_args()

    my_other_function(args.path_to_input_file)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which we may run like&amp;nbsp;this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python my_scripted_action.py --path-to-input-file data/input.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Refactoring requires some knowledge of how to make a command-line interface in our chosen programming language,
but that&amp;#8217;s a writing code skill, not a releasing code&amp;nbsp;skill.&lt;/p&gt;
&lt;p&gt;Remember: we use the same workflow whether we are working on a scripted action or a reusable&amp;nbsp;action.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Create a new project in &lt;a href="https://github.com/opensafely-actions"&gt;https://github.com/opensafely-actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Copy the scripted action to the new project: the scripted action is now a reusable&amp;nbsp;action&lt;/li&gt;
&lt;li&gt;Add &lt;span class="caps"&gt;README&lt;/span&gt;.md&lt;/li&gt;
&lt;li&gt;Add action.yaml, which contains the run&amp;nbsp;command&lt;/li&gt;
&lt;li&gt;Point the existing project to the reusable action like&amp;nbsp;this&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;my_reusable_action&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;csv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remember: we use the same workflow whether we are working on a scripted action or a reusable&amp;nbsp;action.&lt;/p&gt;
&lt;h2&gt;Why create reusable&amp;nbsp;actions?&lt;/h2&gt;
&lt;p&gt;By decoupling scripted actions from their projects&amp;nbsp;we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a location for making improvements (a new&amp;nbsp;project)&lt;/li&gt;
&lt;li&gt;Access a mechanism for sharing&amp;nbsp;improvements&lt;/li&gt;
&lt;li&gt;Access a mechanism for receiving credit for our work&amp;nbsp;(potentially!)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Security&amp;nbsp;redux&lt;/h2&gt;
&lt;p&gt;OpenSAFELY restricts access to the Internet;&amp;nbsp;only&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/opensafely"&gt;https://github.com/opensafely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/opensafely-actions"&gt;https://github.com/opensafely-actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;are accessible, by&amp;nbsp;proxy.&lt;/p&gt;
&lt;p&gt;We have more control over these GitHub organisations than we do over software repositories and&amp;nbsp;mirrors.&lt;/p&gt;
&lt;p&gt;Reusable actions have a similar security profile to scripted&amp;nbsp;actions.&lt;/p&gt;
&lt;h2&gt;Where can I find reusable&amp;nbsp;actions?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Actions Registry: &lt;a href="https://actions.opensafely.org/"&gt;https://actions.opensafely.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/opensafely-actions"&gt;https://github.com/opensafely-actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://docs.opensafely.org/actions-reusable/"&gt;https://docs.opensafely.org/actions-reusable/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Talks"/><category term="OpenSAFELY"/><category term="TRE"/></entry><entry><title>A Constellation of Data Visualization Tools</title><link href="https://www.dillingham.me.uk/2022/06/23/data-visualization-tools.html" rel="alternate"/><published>2022-06-23T00:00:00+01:00</published><updated>2022-06-23T00:00:00+01:00</updated><author><name>Iain Dillingham</name></author><id>tag:www.dillingham.me.uk,2022-06-23:/2022/06/23/data-visualization-tools.html</id><summary type="html">&lt;p&gt;I gave a short talk today called &lt;em&gt;A Constellation of Data Visualization Tools: Vega, Vega-Lite, and Altair&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The first part of the talk was a brief history of data visualization tools.
I described how the ideas in Leland Wilkinson&amp;#8217;s &lt;em&gt;The Grammar of Graphics&lt;/em&gt; are related to
those in ggplot2 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I gave a short talk today called &lt;em&gt;A Constellation of Data Visualization Tools: Vega, Vega-Lite, and Altair&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The first part of the talk was a brief history of data visualization tools.
I described how the ideas in Leland Wilkinson&amp;#8217;s &lt;em&gt;The Grammar of Graphics&lt;/em&gt; are related to
those in ggplot2;
and those in D3.js, Vega, Vega-Lite, and&amp;nbsp;Altair.&lt;/p&gt;
&lt;p&gt;The second part of the talk was a demonstration of Vega, Vega-Lite, and Altair.
Using the editor and the examples,
I showed
that the &lt;span class="caps"&gt;JSON&lt;/span&gt; objects of a Vega specification are transformed into WebGL or &lt;span class="caps"&gt;SVG&lt;/span&gt; graphics by the runtime;
that the &lt;span class="caps"&gt;JSON&lt;/span&gt; objects of a Vega-Lite specification are transformed into the &lt;span class="caps"&gt;JSON&lt;/span&gt; objects of a Vega specification by the runtime;
and that the Python objects produced by Altair are serialized into the &lt;span class="caps"&gt;JSON&lt;/span&gt; objects of a Vega-Lite&amp;nbsp;specification.&lt;/p&gt;
&lt;p&gt;The third part of the talk related Vega, Vega-Lite, and Altair to the &lt;a href="https://www.bennett.ox.ac.uk/"&gt;Bennett Institute&lt;/a&gt; and &lt;a href="https://www.opensafely.org/"&gt;OpenSAFELY&lt;/a&gt;.
Vega and Vega-Lite specifications are well suited to manual (human) and automated (machine) output checking.
They can be themed,
so a house style can be developed by a designer and applied by a researcher.
Finally, they have expressive power and are effective:
the former means they are capable of generating a large variety and quantity of ideas;
the latter means they perform well,
when compared to other notations,
on the &lt;em&gt;cognitive dimensions of notations&lt;/em&gt;&amp;nbsp;framework.&lt;/p&gt;</content><category term="Talks"/><category term="data-visualization"/><category term="vega"/><category term="vega-lite"/><category term="altair"/></entry></feed>