<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Eddie Summers</title>
    <link>https://eddie-summers.com/</link>
    <description>Recent content on Eddie Summers</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-uk</language>
    <lastBuildDate>Tue, 06 Sep 2022 10:00:00 +0000</lastBuildDate><atom:link href="https://eddie-summers.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Validator Pattern</title>
      <link>https://eddie-summers.com/articles/programming/validator-pattern/</link>
      <pubDate>Tue, 06 Sep 2022 10:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/programming/validator-pattern/</guid>
      
      <description>&lt;p&gt;Needing to validate that the properties of some data match your expectations is a common problem, whether that&amp;rsquo;s validating that the invariants of some domain construct are respected, or that the format of a request received from a client is as you expect. Some languages allow you to express rules like this as &lt;a href=&#34;http://blog.cleancoder.com/uncle-bob/2021/06/29/MoreOnTypes.html&#34;&gt;part of the type system&lt;/a&gt;, but for languages that don&amp;rsquo;t, we can do better than the usual chain of &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else if&lt;/code&gt; statements.&lt;/p&gt;
&lt;p&gt;The example below assumes you&amp;rsquo;re using Kotlin on the Spring framework, and want to take advantage of &lt;a href=&#34;https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc&#34;&gt;request-context exception handling&lt;/a&gt;. You may not wish to throw an exception immediately when a rule fails, but instead e.g. return a &lt;code&gt;false&lt;/code&gt; value if any rule is violated, and make a decision based on that.&lt;/p&gt;
&lt;h2 id=&#34;elements&#34;&gt;Elements&lt;/h2&gt;
&lt;p&gt;First, we need to define a &lt;code&gt;Rule&lt;/code&gt;, to express a reusable constraint:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Rule&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;isInvalid&lt;/span&gt;(): Boolean
  &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;fail&lt;/span&gt;()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, a &lt;code&gt;Validator&lt;/code&gt; to manage and execute a list of &lt;code&gt;Rules&lt;/code&gt;. For readers unfamiliar with Kotlin, &lt;code&gt;apply&lt;/code&gt; is a &lt;a href=&#34;https://kotlinlang.org/docs/scope-functions.html&#34;&gt;scope function&lt;/a&gt; allowing us to execute the lambda and return &lt;code&gt;this&lt;/code&gt; in one step.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Validator&lt;/span&gt;(&lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; rules: MutableList&amp;lt;Rule&amp;gt; = mutableListOf()) {

  &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;validate&lt;/span&gt;() = rules.firstOrNull { &lt;span style=&#34;color:#ff79c6&#34;&gt;it&lt;/span&gt;.isInvalid() }&lt;span style=&#34;color:#ff79c6&#34;&gt;?.&lt;/span&gt;fail()

  &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;specify&lt;/span&gt;(rule: Rule) = &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;.apply { rules.add(rule) }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can define a few &lt;code&gt;Rules&lt;/code&gt;, e.g.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ShouldInclude&lt;/span&gt;(&lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; value: Any?, &lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; description: String) : Rule {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;isInvalid&lt;/span&gt;() = value &lt;span style=&#34;color:#ff79c6&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;null&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;fail&lt;/span&gt;() {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;throw&lt;/span&gt; InvalidPayloadException(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;$description&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt; field is missing from the request.&amp;#34;&lt;/span&gt;)
  }
}

&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ShouldHaveStrongPassword&lt;/span&gt;(&lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; password: String) : Rule {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;isInvalid&lt;/span&gt;(): Boolean = password.length &amp;lt; &lt;span style=&#34;color:#bd93f9&#34;&gt;16&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;fail&lt;/span&gt;() = &lt;span style=&#34;color:#ff79c6&#34;&gt;throw&lt;/span&gt; WeakPasswordException()
}

&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ShouldHaveUniqueUsername&lt;/span&gt;(
  &lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; username: String,
  &lt;span style=&#34;color:#ff79c6&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; userService: UserService
) : Rule {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;isInvalid&lt;/span&gt;(): Boolean = userService.getByUsername(username) &lt;span style=&#34;color:#ff79c6&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;null&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;fail&lt;/span&gt;() = &lt;span style=&#34;color:#ff79c6&#34;&gt;throw&lt;/span&gt; DuplicateUsernameException()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;
&lt;p&gt;So if we now wanted to validate that a request to register a new user was valid, we could use them like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;@PostMapping
&lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;register&lt;/span&gt;(@RequestBody body: RegistrationRequest): ResponseEntity&amp;lt;Any&amp;gt; {

  Validator()
    .specify(ShouldInclude(body.firstName, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;First name&amp;#34;&lt;/span&gt;))
    .specify(ShouldInclude(body.surname, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Surname&amp;#34;&lt;/span&gt;))
    .specify(ShouldInclude(body.email, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Email address&amp;#34;&lt;/span&gt;))
    .specify(ShouldInclude(body.password, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Password&amp;#34;&lt;/span&gt;))
    .specify(ShouldHaveStrongPassword(body.password&lt;span style=&#34;color:#ff79c6&#34;&gt;!!&lt;/span&gt;))
    .specify(ShouldHaveUniqueUsername(body.email&lt;span style=&#34;color:#ff79c6&#34;&gt;!!&lt;/span&gt;, userService))
    .validate()

  userService.register(&lt;span style=&#34;color:#ff79c6&#34;&gt;..&lt;/span&gt;.)

  &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; ResponseEntity(HttpStatus.CREATED)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rules with a general scope like &lt;code&gt;ShouldInclude&lt;/code&gt; or e.g. &lt;code&gt;ShouldBeValidUserId&lt;/code&gt; can be reused in multiple places, and since we throw the relevant exception (or return &lt;code&gt;false&lt;/code&gt;, if you prefer) the moment we encounter a failing rule, we can order them so that inputs to later rules can be assumed to be valid according to earlier constraints. In the example controller method above, we can cast &lt;code&gt;body.email&lt;/code&gt; and &lt;code&gt;body.password&lt;/code&gt; to non-nullable &lt;code&gt;Strings&lt;/code&gt; with &lt;code&gt;!!&lt;/code&gt; because we&amp;rsquo;ve already checked them with &lt;code&gt;ShouldInclude&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;going-further&#34;&gt;Going Further&lt;/h2&gt;
&lt;p&gt;Naming constraints using &lt;code&gt;Rule&lt;/code&gt; types allows you to represent the validation logic in a more declarative style. If you had a need for it you could create special combination rules like &lt;code&gt;AndRule&lt;/code&gt; or &lt;code&gt;OrRule&lt;/code&gt; that compose their constraints from other rules, and treat them specially in the &lt;code&gt;Validator&lt;/code&gt;, so as to say something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;Validator()
  .specifyEither(
    ShouldBeValidUserId(body.userId),
    ShouldBeValidEmailAddress(body.email)
  )
  &lt;span style=&#34;color:#ff79c6&#34;&gt;..&lt;/span&gt;.
  .validate()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      
    </item>
    
    <item>
      <title>Creating a Useful Todoist Dashboard</title>
      <link>https://eddie-summers.com/articles/productivity/todoist-queue/</link>
      <pubDate>Mon, 06 Jun 2022 13:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/productivity/todoist-queue/</guid>
      
      <description>&lt;blockquote&gt;
&lt;p&gt;Fair warning: if you don&amp;rsquo;t use &lt;a href=&#34;https://todoist.com/app/&#34;&gt;Todoist&lt;/a&gt;, this may not be very helpful. The concepts discussed here can probably be applied to other task managers, but I make no guarantees!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As I mentioned in &lt;a href=&#34;https://eddie-summers.com/articles/productivity/todo-system/&#34; title=&#34;the previous article&#34;&gt;the previous article&lt;/a&gt;, one of the key design concepts for a helpful to-do system is the ability to hide tasks that aren&amp;rsquo;t relevant right now. This is important for realizing the power a to-do system has for unblocking procrastination: if your workload feels manageable, you are much more able to manage doing it.&lt;/p&gt;
&lt;p&gt;I alluded to the idea of using something like &lt;a href=&#34;https://todoist.com/help/articles/introduction-to-filters&#34;&gt;Todoist filters&lt;/a&gt; to create a view that presents you only the tasks you care about at the moment. This ability to define arbitrarily complex and detailed views is for me the killer Todoist feature.&lt;/p&gt;
&lt;p&gt;The way this works in my system is that tasks are only assigned a due date if necessary; otherwise, I deliberately go through my projects once a week (or some other regular basis) to assign tasks to the queue of &amp;ldquo;current&amp;rdquo; or &amp;ldquo;active&amp;rdquo; ones. It&amp;rsquo;s up to me to keep this queue to a length I think is manageable.&lt;/p&gt;
&lt;p&gt;Then, the dashboard can display the following groups of tasks, in order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Those that are overdue&lt;/li&gt;
&lt;li&gt;Those that are due today&lt;/li&gt;
&lt;li&gt;Those that have been tagged for the queue&lt;/li&gt;
&lt;li&gt;Those that are due later this week&lt;/li&gt;
&lt;li&gt;Those that are blocked&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way, I only see the minimum set of tasks I need to, and I can focus on them more easily. You can move these blocks around by editing the query. This order makes sense to me - tasks that are due on a certain date appear at the bottom and make their way up until they leapfrog the queue and are due today.&lt;/p&gt;
&lt;p&gt;I use a tag called &lt;code&gt;Queue&lt;/code&gt; to designate tasks for this queue, and one called &lt;code&gt;Blocked&lt;/code&gt; to visually separate tasks I can&amp;rsquo;t work on right now. The following query can accomplish this (I call this filter view &lt;strong&gt;Now&lt;/strong&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;!@Blocked &amp;amp; !Subtask &amp;amp; (Overdue | Today),
!@Blocked &amp;amp; !Subtask &amp;amp; !Today &amp;amp; !Overdue &amp;amp; @Queue,
!@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; due before: Sunday,
!@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; Sunday,
@Blocked &amp;amp; !Subtask &amp;amp; @Queue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You will probably also want a dedicated filter to list tasks for your regular refinement/tagging, which I call &lt;strong&gt;Backlog&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;!@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; No due date
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;supporting-separate-projects&#34;&gt;Supporting Separate Projects&lt;/h2&gt;
&lt;p&gt;If, like me, you also manage your work at your job using the same system, you probably don&amp;rsquo;t want your work tasks to appear in the &lt;strong&gt;Now&lt;/strong&gt; view, or in your &lt;strong&gt;Backlog&lt;/strong&gt;. You may also have other projects you want to exclude from the system, e.g. school work or a side business project that you handle differently.&lt;/p&gt;
&lt;p&gt;Rather than explicitly excluding such projects from your filters, you can instead group all &amp;ldquo;normal&amp;rdquo; projects under a project called e.g. &lt;code&gt;Queueable&lt;/code&gt;, and add this as another condition in your filters:&lt;/p&gt;
&lt;h3 id=&#34;now&#34;&gt;Now&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; (Overdue | Today),
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !Today &amp;amp; !Overdue &amp;amp; @Queue,
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; due before: Sunday,
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; Sunday,
##Queueable &amp;amp; @Blocked &amp;amp; !Subtask &amp;amp; @Queue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;backlog&#34;&gt;Backlog&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; No due date
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;start-dates&#34;&gt;Start Dates&lt;/h2&gt;
&lt;p&gt;Eagle-eyed readers may have noticed that my system only allows a week&amp;rsquo;s notice before something becomes overdue: tasks with due dates only enter the &lt;strong&gt;Now&lt;/strong&gt; view when they are due before or on the end of this week. Ideally, we would like to be able to specify a longer lead time for some tasks, as some may take more thought, planning, or effort than others. Some task managers, like &lt;a href=&#34;https://www.omnigroup.com/omnifocus/&#34;&gt;Omnifocus&lt;/a&gt;, have a dedicated notion of start dates (called &amp;ldquo;defer dates&amp;rdquo; in Omnifocus), but Todoist unfortunately lacks them.&lt;/p&gt;
&lt;p&gt;Many people have proposed clever workarounds, but I&amp;rsquo;ve stuck with a fairly simple one. I have three tags called &lt;code&gt;1w&lt;/code&gt;, &lt;code&gt;2w&lt;/code&gt; and &lt;code&gt;4w&lt;/code&gt;. These represent the lead time I want a task to have. If I want a task that has a due date to show up in the &lt;strong&gt;Now&lt;/strong&gt; view before it would naturally fall into it, I can add one of these tags, and adjust the &lt;strong&gt;Now&lt;/strong&gt; filter to the following monster:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; (Overdue | Today),
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !Today &amp;amp; !Overdue &amp;amp; (
  @Queue |
  (
    (
      (@1w &amp;amp; due before: +1 weeks)
      | (@2w &amp;amp; due before: +2 weeks)
      | (@4w &amp;amp; due before: +4 weeks)
    )
    &amp;amp; !(due before: Sunday | Sunday)
  )
),
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; due before: Sunday,
##Queueable &amp;amp; !@Blocked &amp;amp; !Subtask &amp;amp; !@Queue &amp;amp; !Today &amp;amp; !Overdue &amp;amp; Sunday,
##Queueable &amp;amp; @Blocked &amp;amp; !Subtask &amp;amp; (
  @Queue |
  (
    due before: Sunday
    | Sunday
    | (@1w &amp;amp; due before: +1 weeks)
    | (@2w &amp;amp; due before: +2 weeks)
    | (@4w &amp;amp; due before: +4 weeks)
  )
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In other words, the queue section now shows tasks that are inside the defined window but not due within the next week. Now, if a task is due in two weeks&#39; time and is tagged with &lt;code&gt;2w&lt;/code&gt;, it will appear in the queue section. As we arrive on the Monday of the week in which it&amp;rsquo;s due, it will leave the queue section and appear on its due date with the other tasks due that day. I find this flow quite intuitive, and often use these for things like preparing for a loved one&amp;rsquo;s birthday (&lt;code&gt;4w&lt;/code&gt;) or renewing my car insurance (&lt;code&gt;2w&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;This idea pairs particularly well with recurring tasks. With the car insurance example, I can set a task to renew it &lt;code&gt;every 15th July&lt;/code&gt; and tag it with &lt;code&gt;2w&lt;/code&gt;, safe in the knowledge that I can completely forget about it until it appears in my &lt;strong&gt;Now&lt;/strong&gt; view again.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>AI Racing Driver</title>
      <link>https://eddie-summers.com/projects/ai-racing-driver/</link>
      <pubDate>Sat, 07 May 2022 08:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/ai-racing-driver/</guid>
      
      <description>
&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/IQKXmB3zY1I&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;My dissertation project for my master&amp;rsquo;s degree explored the use of deep reinforcement learning for certain challenges remaining in the development of fully autonomous self-driving cars: namely navigating unfamiliar environments and handling low-grip conditions e.g. due to poor weather. The simplest test bed for this was to use a racing simulator - &lt;a href=&#34;http://torcs.sourceforge.net/&#34;&gt;TORCS&lt;/a&gt; in this case - and train an agent to play it from scratch using the &lt;a href=&#34;https://arxiv.org/pdf/1802.09477.pdf&#34;&gt;TD3&lt;/a&gt; algorithm (twin delayed deep deterministic policy gradient).&lt;/p&gt;
&lt;p&gt;After some fine-tuning I was able to show that trained agents were able to safely navigate tracks they&amp;rsquo;d never seen before at a reasonable speed, as well as learn to handle dirt surfaces. This usually required roughly a million training steps on a sufficiently challenging track, which took around eight hours using my particular setup. Note that since this used a &lt;a href=&#34;https://datascience.stackexchange.com/questions/20535/what-is-experience-replay-and-what-are-its-benefits&#34;&gt;replay buffer&lt;/a&gt; batch size of 256, this represents a total sampling of 256 million state transition pairs.&lt;/p&gt;
&lt;p&gt;The video at the top of this page is of an agent (&lt;code&gt;v53_a&lt;/code&gt;) driving on a track that TORCS calls &lt;code&gt;road/wheel-2&lt;/code&gt;, but is in fact a replica of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Suzuka_International_Racing_Course&#34;&gt;Suzuka circuit&lt;/a&gt; in Japan. In this case it also trained on this track, which explains why it has learned a fairly good racing line in places (e.g. turn 9 at 1:00). This level of ability was less common on unseen tracks, but did occur sometimes.&lt;/p&gt;
&lt;p&gt;You can read my &lt;a href=&#34;https://github.com/esummers1/td3-racing-driver/raw/main/docs/Dissertation.pdf&#34;&gt;full write-up&lt;/a&gt; or try it out yourself using the repository &lt;a href=&#34;https://github.com/esummers1/td3-racing-driver&#34;&gt;here&lt;/a&gt; (Linux required).&lt;/p&gt;
&lt;h2 id=&#34;other-videos&#34;&gt;Other Videos&lt;/h2&gt;
&lt;p&gt;This video shows another agent (&lt;code&gt;v53_g_1&lt;/code&gt;) driving on a dirt circuit (&lt;code&gt;dirt/dirt-6&lt;/code&gt;). This is the track it performed its training on.&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/h2jTvrstJec&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;This last video shows the same agent driving on &lt;code&gt;road/aalborg&lt;/code&gt;, which it had not seen before. This was one of the tracks I used to evaluate various agents, and proved to be particularly hard to complete safely owing to its tight corners. Interestingly, only agents trained on dirt tracks were able to generalize to it, although I suspect this might be due to their tendency to drive at a lower speed than those trained on road circuits.&lt;/p&gt;

&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/bo012LVmgmQ&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

</description>
      
    </item>
    
    <item>
      <title>Designing a Useful To-Do List</title>
      <link>https://eddie-summers.com/articles/productivity/todo-system/</link>
      <pubDate>Wed, 16 Feb 2022 16:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/productivity/todo-system/</guid>
      
      <description>&lt;p&gt;Procrastination has had a significant impact on me at several points in my life. The most egregious example happened during my final year at university, on my undergrad degree in sport &amp;amp; exercise science. My dissertation - the write-up for my final-year project - was due in April, and I had had the whole academic year since October to work on it. However, at the start of April, all I had managed to do was the experimental trial itself - a simple study of the effect of a certain kind of warm-up drill on activation of the target muscles during subsequent exercise. I had done very little background research, and none of the write-up.&lt;/p&gt;
&lt;p&gt;You might think that the looming deadline, coupled with the enormous amount of work left to do, would encourage me to do some of it. However, it had the opposite effect; the closer the deadline got, the less inclined I felt to do anything, despite my increasing fear. The &lt;em&gt;week of the deadline&lt;/em&gt; arrived, and I still hadn&amp;rsquo;t started work. In the end, I had to work from about 2 PM on the Wednesday, right up until the hand-in deadline at 5 PM on Thursday. My memory of this period is quite foggy, but I think I fell into a routine of working for three hours, taking a caffeine pill, and having a 20-minute nap. As you might imagine, I could have done a lot better on that piece of work than I did.&lt;/p&gt;
&lt;p&gt;Tim Urban of &lt;a href=&#34;https://waitbutwhy.com/&#34;&gt;Wait But Why&lt;/a&gt; wrote a &lt;a href=&#34;https://waitbutwhy.com/2013/10/why-procrastinators-procrastinate.html&#34;&gt;fantastic article&lt;/a&gt; later that year exploring this phenomenon, although I didn&amp;rsquo;t come across it until a few years later. He does a much better job of explaining it than I could, but to me the root of procrastination is fear: any time I realize I&amp;rsquo;m putting off the time I have to do something, it&amp;rsquo;s because I&amp;rsquo;m worried about it. This is either because I know it will be unpleasant, or - as is so much more likely - I&amp;rsquo;m uncertain about how one part of it will work, or what I will need to do, and am afraid of that uncertainty.&lt;/p&gt;
&lt;p&gt;In the years since then, I&amp;rsquo;ve done a reasonable job of curing this behaviour in myself, though I have lapses every now and then. Somewhat unhelpfully, one of the things that helped was arranging my life in such a way that the things I have to do are more likely to be things I want to do: I enjoy my work and I choose the side projects I work on. However, for everything else, the systems by which I organize myself help enough for me to get by.&lt;/p&gt;
&lt;h2 id=&#34;to-do-lists&#34;&gt;To-Do Lists&lt;/h2&gt;
&lt;p&gt;The classic idea of a to-do list is just a list of things you need to do, on paper. You can develop this idea by having separate lists for different projects, or work contexts, or any number of other different ways. Much has been said about this topic, so I&amp;rsquo;m just going to focus on things that have helped me.&lt;/p&gt;
&lt;p&gt;The most important benefit of the to-do list is strongly related to the need for &lt;a href=&#34;https://eddie-summers.com/articles/productivity/never-forget-anything/&#34;&gt;note-taking&lt;/a&gt;: the fact that the brain is for thinking, not for remembering. As long as something you want to remember exists only in your head, it&amp;rsquo;s at risk.&lt;/p&gt;
&lt;h2 id=&#34;ingress&#34;&gt;Ingress&lt;/h2&gt;
&lt;p&gt;Therefore, to me, the first requirement for a good to-do system is that it must be easy and fast to add items to it, wherever you are. The more steps are required for this, the less likely you are to add things, meaning they will stay at-risk in your mind. I have experimented with things like &lt;a href=&#34;https://bulletjournal.com/&#34;&gt;bullet journalling&lt;/a&gt; for managing tasks, but have always gone back towards using an electronic system - specifically Todoist, though I will leave the reasons to choose it over others for another time.&lt;/p&gt;
&lt;p&gt;Something that can live as an app on your phone, and on your desktop machine (whether that be natively or in the browser), is so superior for task ingress to anything else that there is no competition. Note that this also excludes digital versions of the paper to-do list, including using plain text lists, or more sophisticated (and admittedly excellent) things like &lt;a href=&#34;https://orgmode.org/&#34;&gt;org-mode&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;access&#34;&gt;Access&lt;/h2&gt;
&lt;p&gt;While you must be able to add a new item from anywhere, it is not necessarily true that you should be able to use all the features of your system from anywhere. Usually, entering tasks and actually doing the work they tell you to are separate activities. Personally, I find that I&amp;rsquo;m almost always at a computer when actually getting stuff done - meaning my phone is more for adding tasks, or being reminded of time- or location-sensitive things that don&amp;rsquo;t really live in the to-do system. This means that you can combine systems usefully - there is no particular reason that your task inbox needs to live in the same application that handles your filtering and displays tasks to you, although it makes things a lot simpler.&lt;/p&gt;
&lt;h2 id=&#34;filtering&#34;&gt;Filtering&lt;/h2&gt;
&lt;p&gt;Even fairly complex to-do systems are not suitable as project management tools, in my opinion - the real value of to-do applications that organize tasks into &amp;ldquo;projects&amp;rdquo; (usually in the &lt;a href=&#34;https://gettingthingsdone.com/&#34;&gt;GTD sense&lt;/a&gt;) is that it allows you to compartmentalize and &lt;strong&gt;hide&lt;/strong&gt; tasks when you don&amp;rsquo;t need to look at them. Non-trivial projects are too non-linear and require too much supporting thought to be managed purely by a to-do list, although you can certainly use to-do lists to collect next actions in the same place that you look for other actions.&lt;/p&gt;
&lt;p&gt;Most people have surely had the experience of feeling like they have too many things to do at once, deciding to write these things down, and realizing that these things were far more manageable than they thought. The real value of using a proper system for managing your tasks is that once these things are out of your mind and on paper, this feeling of overwhelm goes away, or at least reduces.&lt;/p&gt;
&lt;p&gt;However, the danger with a simplistic to-do system is that a very long list of tasks - even if they are quite small - conjures a similar feeling to having three or four things swirling around your head at once. The enlightened to-do system designer designs the system to do two things well: accept new items, and hide ones you don&amp;rsquo;t need to work on now.&lt;/p&gt;
&lt;p&gt;A common way people use to-do managers is to try to assign every task a due date, so nothing gets forgotten. However, we all have days where little gets done, or you don&amp;rsquo;t end up having the amount of time you thought you did, so lists like this quickly end up with lots of items in &amp;ldquo;Overdue&amp;rdquo;, which is really not much better than having them in your head. To me, the correct approach is to only assign due dates where necessary, and instead have tasks enter your &amp;ldquo;do now / this week&amp;rdquo; list deliberately.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Incidentally, my only real frustration with Todoist is that it doesn&amp;rsquo;t support the notion of start/defer dates, as &lt;a href=&#34;https://www.omnigroup.com/omnifocus/&#34;&gt;Omnifocus&lt;/a&gt; does, but I have a workaround which I&amp;rsquo;ll write about another time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The way I do this is using a &lt;a href=&#34;https://todoist.com/help/articles/introduction-to-filters&#34;&gt;Todoist filter&lt;/a&gt;, i.e. a custom view defined using a simple query language. I have a tag I assign to tasks that I want to work on &amp;ldquo;soon&amp;rdquo;, and I have a view that shows me tasks that are due soon, plus those that have this tag. Everything else is hidden, and I only go through those tasks once a week, tagging more tasks that I want to work on, to assign them back to the main view (this can be made easier by filtering for tasks that have neither tags nor due dates!). This &amp;ldquo;now&amp;rdquo; view is roughly arranged in order: first tasks due today, then tasks with this tag, then tasks due on days later in the week.&lt;/p&gt;
&lt;p&gt;This way, there can be hundreds of tasks in the system that I can &lt;em&gt;safely forget about&lt;/em&gt;, because I have a system for reviewing them regularly when I&amp;rsquo;m in the frame of mind for prioritizing and refining tasks, which makes it easy to reason about work in the knowledge that I don&amp;rsquo;t have to do it right now. This separation is important: this is quite a different mode to the daily mode of opening the task manager and seeing what past-me thought it was important to work on.&lt;/p&gt;
&lt;p&gt;This system is naturally imperfect, in that I am imperfect: sometimes I still procrastinate on items in the list, but this becomes much more obvious when there are only 5-10 items due this week, and a particular task is lingering from week to week. When this happens, it often helps to write down what&amp;rsquo;s causing me to worry about it, since I often know, but am lying to myself about it. Once this is out in the open, it feels a lot less threatening, and I often find the task gets done.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Your system must respect the following truths:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;People are bad at remembering things&lt;/li&gt;
&lt;li&gt;People are bad at thinking about more than one thing at once&lt;/li&gt;
&lt;li&gt;An intimidating amount of work to do can seem infinite, &lt;strong&gt;but&lt;/strong&gt; work that is out of sight is out of mind&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And therefore do the following before all else:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow you to add items frictionlessly&lt;/li&gt;
&lt;li&gt;Hide items that can&amp;rsquo;t or shouldn&amp;rsquo;t be worked on right now&lt;/li&gt;
&lt;/ul&gt;
</description>
      
    </item>
    
    <item>
      <title>Economy of Expression</title>
      <link>https://eddie-summers.com/articles/programming/economy-of-expression/</link>
      <pubDate>Sun, 11 Oct 2020 12:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/programming/economy-of-expression/</guid>
      
      <description>&lt;p&gt;I&amp;rsquo;ve been thinking a lot lately about the differences between different programming languages. Languages can be celebrated over others for their features, e.g. static typing over dynamic typing, or supporting multiple inheritance, or the quality of their standard libraries. All of these are important, but I would like to argue that  &lt;em&gt;economy of expression&lt;/em&gt; should be considered among a language&amp;rsquo;s most important features.&lt;/p&gt;
&lt;p&gt;In a language which has good economy of expression, developer productivity is increased for two big reasons: first, the same behaviour can be created with less code, which takes less time to write and has less room for syntactical mistakes. Second, when working with others or in a large project, it is easier to understand at a glance what some piece of code is doing, and hence takes less time to add something new.&lt;/p&gt;
&lt;p&gt;Note that I am not advocating that languages should be as terse or brief as possible: that is economy of characters, not of expression. Something is expressive to the reader if it conveys its meaning, and something has good economy of expression if a lot of meaning can be conveyed with less verbose language. Excess boilerplate code is hard to read, and &lt;a href=&#34;https://www.danjb.com/tech_blog/readable_code&#34;&gt;readability is crucial&lt;/a&gt; in scenarios where code being easy to understand is important to the project&amp;rsquo;s success, i.e. all software projects.&lt;/p&gt;
&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s compare some related languages in their ability to do two things, in the idiomatic style of each language.&lt;/p&gt;
&lt;p&gt;In my job, I spend a lot of time working with the Salesforce platform, which provides a server-side language called &lt;a href=&#34;https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_dev_guide.htm&#34;&gt;Apex&lt;/a&gt;. This is derived from an early version of Java - so early in fact that it lacks support for generics! It certainly does not support lambda expressions, or higher-order functions of any kind.&lt;/p&gt;
&lt;h3 id=&#34;task-1---list-transformation&#34;&gt;Task 1 - List Transformation&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s imagine we have some Animals, and we want to list the ages of all the gorillas:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;getGorillaAgesFrom&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Animal&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;&lt;/span&gt; animals&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
  List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;&lt;/span&gt; ages &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;new&lt;/span&gt; List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;();&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Animal animal &lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; animals&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;animal&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;species&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;==&lt;/span&gt; &amp;#39;Gorilla&amp;#39;&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
      ages&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;add&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;animal&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;age&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;);&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; ages&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, for the same thing in modern Java:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;getGorillaAgesFrom&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;List&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;&lt;/span&gt;Animal&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;gt;&lt;/span&gt; animals&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; animals&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;stream&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt;
      &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;filter&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;animal &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; animal&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;getSpecies&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;().&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;equals&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Gorilla&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;))&lt;/span&gt;
      &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;map&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;animal&lt;span style=&#34;color:#ff79c6&#34;&gt;::&lt;/span&gt;getAge&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt;
      &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;collect&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Collectors&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;toList&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;());&lt;/span&gt;
&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, finally, in &lt;a href=&#34;https://kotlinlang.org/&#34;&gt;Kotlin&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;fun&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;getGorillaAgesFrom&lt;/span&gt;(animals: List&amp;lt;Animal&amp;gt;): List&amp;lt;Int&amp;gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; animals.filter { &lt;span style=&#34;color:#ff79c6&#34;&gt;it&lt;/span&gt;.species &lt;span style=&#34;color:#ff79c6&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Gorilla&amp;#34;&lt;/span&gt; }.map { &lt;span style=&#34;color:#ff79c6&#34;&gt;it&lt;/span&gt;.age }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Java&amp;rsquo;s huge advantage over Apex of supporting higher-order functions allows it to express the same idea as the Apex code in a neater manner. Kotlin, which shortcuts traditional Java getters and setters using its property convention, and whose &lt;code&gt;Collections&lt;/code&gt; implementation does away with the need for Java&amp;rsquo;s calls to &lt;code&gt;stream()&lt;/code&gt; and &lt;code&gt;collect()&lt;/code&gt;, goes even further.&lt;/p&gt;
&lt;p&gt;I would argue that even though the Java example is much-improved, the Kotlin code is so expressive that it almost reads like a single sentence. The syntax it lacks compared to the Java equivalent is purely boilerplate or logistical, meaning more of what remains expresses the programmer&amp;rsquo;s intent. Comparing the Kotlin example with the Apex example is particularly eye-opening. Spare a thought for Apex developers who can&amp;rsquo;t implement even rudimentary type-safe streams, due to the lack of generics support!&lt;/p&gt;
&lt;h3 id=&#34;task-2---class-definition&#34;&gt;Task 2 - Class Definition&lt;/h3&gt;
&lt;p&gt;For this exercise, Apex and Java are essentially the same, so I will just use Java.&lt;/p&gt;
&lt;p&gt;Imagine we want to declare a class with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An immutable field that is always required&lt;/li&gt;
&lt;li&gt;A mutable field that is always required&lt;/li&gt;
&lt;li&gt;A mutable field that is optional, and has some default value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Barring the use of third-party libraries like &lt;a href=&#34;https://projectlombok.org/&#34;&gt;Lombok&lt;/a&gt;, which had to be created to solve the problem I&amp;rsquo;m about to demonstrate, here&amp;rsquo;s how this would be done in Java:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Dummy&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;final&lt;/span&gt; Object immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;private&lt;/span&gt; Object mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;private&lt;/span&gt; Object optional&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Dummy&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Object immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;,&lt;/span&gt; Object mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;,&lt;/span&gt; mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;);&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Dummy&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Object immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;,&lt;/span&gt; Object mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;,&lt;/span&gt; Object optional&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;immutable&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;mutable&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;optional&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; optional&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; Object &lt;span style=&#34;color:#50fa7b&#34;&gt;getImmutable&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; immutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; Object &lt;span style=&#34;color:#50fa7b&#34;&gt;getMutable&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; Object &lt;span style=&#34;color:#50fa7b&#34;&gt;getOptional&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; optional&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#8be9fd&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;setMutable&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Object mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;mutable&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; mutable&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;

  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#8be9fd&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;setOptional&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;(&lt;/span&gt;Object optional&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
    &lt;span style=&#34;color:#ff79c6&#34;&gt;this&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#50fa7b&#34;&gt;optional&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; optional&lt;span style=&#34;color:#ff79c6&#34;&gt;;&lt;/span&gt;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, the Kotlin version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Dummy&lt;/span&gt;(&lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; immutable: Any, &lt;span style=&#34;color:#ff79c6&#34;&gt;var&lt;/span&gt; mutable: Any, &lt;span style=&#34;color:#ff79c6&#34;&gt;var&lt;/span&gt; optional: Any = &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are a couple of things to note here. One, this code is much easier to write. Yes, modern IDEs can generate things like getters and setters for you, but shouldn&amp;rsquo;t we let the compiler do that instead, as Kotlin&amp;rsquo;s does? Two, the Kotlin version is not only equivalent, but easier to use from other Kotlin code. Kotlin allows default values for function parameters (including constructors, as we have just seen), but also lets you supply arguments in any order if you name them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-kotlin&#34; data-lang=&#34;kotlin&#34;&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;val&lt;/span&gt; dummy = Dummy(mutable = something, immutable = somethingElse)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This last feature has the added benefit of clearly labelling what each of the arguments is for, making the calling code more understandable.&lt;/p&gt;
&lt;p&gt;These features remove much of the need for overloading methods, which in my opinion should be considered more a workaround than a pattern. Note that this also means Kotlin has little use for the builder pattern, since the primary constructor can be used so flexibly, and other initialization logic can go in a secondary constructor in the class body.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I think that a lot of low-level design choices in programming revolve around making what you write easier to understand. Since languages differ in the expressiveness of their syntaxes, it seems sensible to me to be careful about which we choose to work with - to pick ones which are more expressive. Writing clean and simple code in a verbose and clumsy language, when a better alternative is available, is stepping over pounds to pick up pennies.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Networked Notes</title>
      <link>https://eddie-summers.com/articles/productivity/networked-notes/</link>
      <pubDate>Wed, 30 Sep 2020 12:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/productivity/networked-notes/</guid>
      
      <description>&lt;p&gt;I have &lt;a href=&#34;https://eddie-summers.com/articles/productivity/never-forget-anything/&#34;&gt;written previously&lt;/a&gt; about how I have found VS Code and Markdown to be just the right way for me to take notes about things. To have claimed to have attained &amp;ldquo;note-taking perfection&amp;rdquo; was probably ambitious, but so far not actually wrong - what needs fixing next is access to the information in the notes.&lt;/p&gt;
&lt;p&gt;If you take notes on a computer, they will probably be filed in some kind of directory structure. This is true in a symbolic sense for note-taking applications that organise notes into Notebooks and so on (e.g. Evernote, OneNote), and true in a more literal sense for the Markdown approach I advocated last time.&lt;/p&gt;
&lt;p&gt;The trouble with this is that while it feels productive and &amp;ldquo;organized&amp;rdquo; to file away notes in just the right place, your notes should probably not be modelled on an archive. You should think about your notes as a second human memory, or &lt;em&gt;knowledge base&lt;/em&gt; (as the trendy term is at the moment). Thoughts relate to one another in disorganized, unstructured ways, and surely the best way for you to remember what&amp;rsquo;s in your notes (the point of having them) is to structure them in a manner that feels natural to the brain.&lt;/p&gt;
&lt;h2 id=&#34;networked-notes&#34;&gt;Networked Notes&lt;/h2&gt;
&lt;p&gt;Being a &lt;a href=&#34;https://www.relay.fm/cortex/&#34;&gt;Cortex&lt;/a&gt; fan, I have been &lt;a href=&#34;https://www.relay.fm/cortex/105&#34;&gt;recently introduced&lt;/a&gt; to the idea of &lt;a href=&#34;https://en.wikipedia.org/wiki/Zettelkasten&#34;&gt;Zettelkasten&lt;/a&gt;. In short this is a way of organising notes by means of the connections between them, not by means of some external structure.&lt;/p&gt;
&lt;p&gt;I found that this idea stuck with me - it makes a lot of sense. Advocates of Zettelkasten claim that after a large enough number of notes have built up in your system, you start to see emergent links between distant ideas, and make new connections.&lt;/p&gt;
&lt;h2 id=&#34;tooling&#34;&gt;Tooling&lt;/h2&gt;
&lt;p&gt;I decided to try out this type of system for myself, so the next question was how to integrate this into my current workflow. There are tools that can do this for you e.g. &lt;a href=&#34;https://roamresearch.com/&#34;&gt;Roam&lt;/a&gt; and &lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt;, but as I said, I have already achieved note-taking perfection. The first step was to pull all my notes out into a single directory, so new notes could be added without the friction of having to find a place to file them. But how could I link notes together in a useful fashion in VS Code?&lt;/p&gt;
&lt;p&gt;Luckily I stumbled across &lt;a href=&#34;https://kortina.nyc/essays/suping-up-vs-code-as-a-markdown-notebook/&#34;&gt;this article&lt;/a&gt; by Andy Kortina, which describes an extension he made for VS Code called &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=kortina.vscode-markdown-notes&#34;&gt;Markdown Notes&lt;/a&gt;. It supports wikilink syntax, e.g. &lt;code&gt;[[my-cool-note]]&lt;/code&gt; to link to &lt;code&gt;./my-cool-note.md&lt;/code&gt;, among other things.&lt;/p&gt;
&lt;p&gt;I tried this at first, and it has some very handy features, but I found that it didn&amp;rsquo;t support navigation through wikilinks in the preview pane. To do this you need an extension that completely replaces the preview, e.g. &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced&#34;&gt;Markdown Preview Enhanced&lt;/a&gt; by Yiyi Wang. This did not allow me to style the preview in a manner that I liked, and the feel and readability of the environment were two of the main reasons for picking this way of taking notes.&lt;/p&gt;
&lt;p&gt;Luckily I then discovered &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=svsool.markdown-memo&#34;&gt;Markdown Memo&lt;/a&gt; by Svyat Sobol. This - crucially - allows you to specify labels for wikilinks, e.g. &lt;code&gt;[[my-cool-note|My Cool Note]]&lt;/code&gt;. This makes your notes much more readable in the preview. These links are also navigable in the &lt;em&gt;native&lt;/em&gt; preview pane! Like Markdown Notes, it also supports bi-directional navigation: when a Markdown file is open, the Backlinks context menu (in the Explorer pane) lets you see all the references to the file and navigate backwards by clicking them.&lt;/p&gt;
&lt;p&gt;Markdown Memo also supports wikilink/file refactoring: you can rename a note file and the extension will update all references to it in other notes. It also allows you to do this from a file which references that other note, using the built-in refactoring action.&lt;/p&gt;
&lt;p&gt;Unlike Markdown Notes, Markdown Memo does not offer workspace support for tags in notes - ideally they would be understood as symbols by VS Code and searchable using the References feature, but you can still search using the standard search. I keep tags in the header of each file as front matter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;---
tags: #kotlin #object-orientation
---

&lt;span style=&#34;font-weight:bold&#34;&gt;# My Note&amp;#39;s Heading
&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;style&#34;&gt;Style&lt;/h2&gt;
&lt;p&gt;I am reliably informed that short, atomic notes - i.e. those on a single, confined subject - are easiest to network properly. The best summary of these ideas I&amp;rsquo;ve seen is on &lt;a href=&#34;https://notes.andymatuschak.org/z4SDCZQeRo4xFEQ8H4qrSqd68ucpgE6LU155C&#34;&gt;Andy Matuschak&amp;rsquo;s notes website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What I find helpful about this style is now that I don&amp;rsquo;t feel as if I have to write long-form notes, or find a place for them to go. If I have an idea that I want to keep and think more about later, I can just start writing - and if I remember that I&amp;rsquo;ve written something related before, I can link to it from this note, and visit that other one to see if it needs refining or expanding. As I develop these notes, they may well end up getting expanded into articles for this website, since I can sometimes feel that I want to say more about a topic.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Why Do We Need to Exercise?</title>
      <link>https://eddie-summers.com/articles/fitness/why-do-we-need-to-exercise/</link>
      <pubDate>Sun, 13 Sep 2020 10:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/why-do-we-need-to-exercise/</guid>
      
      <description>&lt;p&gt;Hopefully it&amp;rsquo;s common knowledge by now that exercise is not only beneficial but essential for your health. There are many places you can learn about the benefits of this kind of exercise or that kind, but to my mind something that&amp;rsquo;s rarely well explained is why we actually need to exercise at all.&lt;/p&gt;
&lt;h2 id=&#34;adaptability&#34;&gt;Adaptability&lt;/h2&gt;
&lt;p&gt;Specialism is great in an environment that requires the specialism, but terrible in all others. The most successful species in nature are those which can adapt to changing environmental demands. Because of this, life as it exists today is highly adaptable, within certain limits. The ability of biological systems to adapt to stimuli they receive - to become better at meeting the same challenge next time - is miraculous.&lt;/p&gt;
&lt;p&gt;When you exercise, chemical reactions that take place during the activity trigger a cascade of other effects, leading - with nutrition and rest - to the tissues involved adapting to the stimulus. This adaptation is specific to the stimulus applied: if you exhausted yourself with a long cycle, your leg muscles&#39; ability to resist fatigue will improve. If you lifted heavy weights, more contractile proteins will be laid down and the nervous system&amp;rsquo;s ability to use more of the muscle at one time will increase.&lt;/p&gt;
&lt;p&gt;But nature is ruthless, and until recently, the availability of food could not be guaranteed (for some, it still can&amp;rsquo;t). Muscle tissue is expensive, even if you&amp;rsquo;re not using it. This logic applies to strengthening of the heart and bones as well, and is why we observe that humans respond to physical training, but will revert to their previous condition if training ceases.&lt;/p&gt;
&lt;p&gt;If this balancing mechanism was not present, our evolutionary line would have failed: strenuous prehistoric lives would lead to more and more muscle that would be impossible to feed.&lt;/p&gt;
&lt;h2 id=&#34;interdependency&#34;&gt;Interdependency&lt;/h2&gt;
&lt;p&gt;This is all well and good, but what&amp;rsquo;s not usually considered is that the metabolic processes that support this adaptability are deeply interwoven with the rest of our physiology. Biological systems are heavily interconnected, much more so than ones humans design.&lt;/p&gt;
&lt;p&gt;One of the things humans have evolved to do well is output a lot of work over a long time, most likely for persistence hunting. These systems, such as the relationship between blood glucose and insulin, or the balance between bone formation and resorption, among many others, have evolved to require both sides in order to function. The way to stimulate both sides is - you guessed it - to exercise.&lt;/p&gt;
&lt;p&gt;These systems make up the core part of our physiology - exchange of energy with the environment - so they can&amp;rsquo;t be neglected. With this and the &amp;ldquo;use it or lose it&amp;rdquo; nature of physical adaptation, the implication is clear: &lt;em&gt;the price of being able to do something is that you must do it&lt;/em&gt;, and none of us can now opt out of this trade.&lt;/p&gt;
&lt;h2 id=&#34;balance&#34;&gt;Balance&lt;/h2&gt;
&lt;p&gt;You can think of metabolism as having two sides - the Exercise side and the Feeding side. On the Exercise side, the body uses stored energy and incurs damage to its tissues. This is balanced by the Feeding side, where consumed food is used to replenish the stores and lay down new tissue. Both are obviously happening all the time, but the balance swings back and forth as you exercise, eat, sleep etc.&lt;/p&gt;
&lt;p&gt;The point is that the chemistry of each side doesn&amp;rsquo;t work particularly well when the other doesn&amp;rsquo;t happen enough. They require each other: to oscillate between the two sides is better than to stay in the middle. If you burn 300 extra calories in a day and eat an additional 300, there will be no effect on your weight, but you will be healthier than if you did neither.&lt;/p&gt;
&lt;p&gt;Type-2 diabetes happens when the body becomes insensitive to insulin, i.e. becomes unable to reduce its blood sugar level. This has a number of causes, but the most important one is persistently high blood sugar (over-Feeding). The most effective way to increase insulin sensitivity is regular strenuous exercise.&lt;/p&gt;
&lt;h2 id=&#34;atrophy&#34;&gt;Atrophy&lt;/h2&gt;
&lt;p&gt;If you don&amp;rsquo;t use something, it will be salvaged, to conserve resources. For example, unused muscles will shrink (muscular atrophy), unloaded bones will weaken (osteoporosis), and an unused brain will become rigid and slow down (Alzheimer&amp;rsquo;s).&lt;/p&gt;
&lt;p&gt;The cost of inactivity-related atrophy is therefore much greater than just looking less muscular. They say that you don&amp;rsquo;t stop moving when you get old; you get old when you stop moving. Here are some cross-section scans of the thighs of three different people:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/scans.jpg&#34; alt=&#34;Atrophy vs training&#34;&gt;&lt;/p&gt;
&lt;p&gt;In the middle image, the high quantity of fat, scraggly muscle and infiltration of fat into muscle are all signs of declining health. In fact, muscle strength and mass are good predictors of remaining &lt;em&gt;healthy&lt;/em&gt; lifespan in the elderly.&lt;/p&gt;
&lt;h2 id=&#34;notes&#34;&gt;Notes&lt;/h2&gt;
&lt;p&gt;This post was adapted from my answer to &lt;a href=&#34;https://fitness.stackexchange.com/questions/42874/why-is-exercise-good-for-you/42878#42878&#34;&gt;this StackExchange question&lt;/a&gt;, and as I said in my answer I&amp;rsquo;d strongly recommend reading &lt;a href=&#34;https://www.goodreads.com/book/show/486024.Survival_Of_The_Fittest&#34;&gt;Survival of the Fittest by Mike Stroud&lt;/a&gt;. I first read this in my final year of university (studing sport &amp;amp; exercise science) and found it helpful in unifying all the facts I&amp;rsquo;d been learning.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Herding Cats</title>
      <link>https://eddie-summers.com/projects/herding-cats/</link>
      <pubDate>Mon, 13 Jul 2020 10:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/herding-cats/</guid>
      
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/esummers1/gmtk-game-jam-2020&#34;&gt;Herding Cats&lt;/a&gt; is a browser game created for the &lt;a href=&#34;https://itch.io/jam/gmtk-2020&#34;&gt;GMTK Game Jam 2020&lt;/a&gt;, a 48-hour game-making hackathon. I worked on this game as part of Team Cat Herders. The theme this year was &amp;ldquo;Out of Control&amp;rdquo;, so we decided that literally herding cats would be a fun idea.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://danjb1.itch.io/herding-cats&#34;&gt;You can play the game here&lt;/a&gt;! Please turn your sound on.&lt;/p&gt;
&lt;p&gt;The idea of the game is that the player runs a cattery, where owners drop their cats off for short stays. The player takes on way more business than they can handle, which is a problem because the pen from which owners will collect their cats is small, and the cats are prone to escaping. Cats will avoid  the player and the player&amp;rsquo;s trusty dog, which can be summoned to the player&amp;rsquo;s location with a whistle. They must be herded into the pen to be picked up on time.&lt;/p&gt;
&lt;p&gt;As cats approach their pickup time (shown in the bar at the top), coloured exclamation marks will appear over their heads. The player gains money (points) for each cat delivered on time, as well as a star (life) for delivering several cats in a row. If a cat is not ready for pickup by the time its avatar reaches the end of the bar, the player loses a star. If the star rating reaches zero, the game will end.&lt;/p&gt;
&lt;p&gt;Since the theme was &amp;ldquo;Out of Control&amp;rdquo;, the game is intended to be difficult and overwhelming. It usually feels as if the player is &lt;em&gt;almost&lt;/em&gt; on top of herding all the cats, but this can change quickly.&lt;/p&gt;
&lt;p&gt;Herding Cats runs natively in the browser. We used PixiJS for our rendering engine; luckily its latest versions support TypeScript, which we used for all our logic. The game engine itself was custom and used a component-based architecture to manage the entities&#39; behaviour. Most of the assets we used were created by the team.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>How to Never Forget Anything</title>
      <link>https://eddie-summers.com/articles/productivity/never-forget-anything/</link>
      <pubDate>Fri, 22 May 2020 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/productivity/never-forget-anything/</guid>
      
      <description>&lt;p&gt;I have struggled for many years with how best to do and record things like the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notes about things I&amp;rsquo;ve learned or studied&lt;/li&gt;
&lt;li&gt;Planning projects or events&lt;/li&gt;
&lt;li&gt;Lists of stuff e.g. books to read&lt;/li&gt;
&lt;li&gt;Other random junk&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are lots of tools available to help you keep track of this sort of thing. Evernote, for example, does a great job of capturing &lt;em&gt;stuff&lt;/em&gt; of every kind. Google Keep lets you add notes quickly and easily from anywhere. Notion allows you to build a personal wiki with all sorts of pages. OneNote seems to be able to just about anything. The list goes on.&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;ve found with every one of these - and others - that nothing felt just right. Evernote is clunky, slow and does not produce pleasant-looking notes. Google Keep just doesn&amp;rsquo;t work for long-form notes. Notion has high aspirations but was - at least to my monkey fingers - virtually unusable. OneNote just never felt right - my notes felt hidden and siloed. I even worked for a while writing notes by hand in notebooks, and while this is nice while writing, it&amp;rsquo;s very hard to go back and find what you wrote in a physical book quickly.&lt;/p&gt;
&lt;p&gt;What I needed was something that was lightweight, flexible, and easy to access. And, for someone with a compulsive streak such as me, configurable.&lt;/p&gt;
&lt;h2 id=&#34;enter-markdown&#34;&gt;Enter Markdown&lt;/h2&gt;
&lt;p&gt;Markdown is a widely-used markup language. It&amp;rsquo;s readable, easy to type in and contains features like formatting, hyperlinks to web pages or other files, images, lists and - if you use the GitHub flavour - tables. It will even support LaTeX-brand mathematical typesetting in some versions.&lt;/p&gt;
&lt;p&gt;Plain text has a big advantage over proprietary solutions. If you want to migrate your junk from Evernote to Google Keep, good luck. However if you want to use a different text editor to view and write your notes, no problem!&lt;/p&gt;
&lt;h2 id=&#34;visual-studio-code&#34;&gt;Visual Studio Code&lt;/h2&gt;
&lt;p&gt;My choice for writing, viewing and managing notes is VS Code. There are excellent extensions for working with Markdown - specifically Yu Zhang&amp;rsquo;s &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one&#34;&gt;Markdown All in One&lt;/a&gt;, David Anson&amp;rsquo;s &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint&#34;&gt;markdownlint&lt;/a&gt; and Matt Bierner&amp;rsquo;s necessary &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji&#34;&gt;Markdown Emoji&lt;/a&gt;, to name a few.&lt;/p&gt;
&lt;p&gt;VS Code already has a Markdown Preview feature, which can sit beside a document you&amp;rsquo;re working on and show you a live rendering, with synchronized scrolling and so on. Better yet, since almost every aspect of VS Code is configurable, you can get the preview pane looking just so: the right font, the right size, the right line spacing.&lt;/p&gt;
&lt;p&gt;Since it&amp;rsquo;s designed first as a text/code editor, its features for navigating through files for text blow traditional note-taking apps out of the water. You can traverse the headings and subheadings in a Markdown file using the &lt;code&gt;Go to symbol in editor&lt;/code&gt; action, or quickly jump to a file by name. The usual ability to find/replace text across files using plain search terms or regular expressions is a given. If you like to use Vim or Emacs, there are emulator/keymap plugins available.&lt;/p&gt;
&lt;p&gt;Its colour scheme customizations are also very powerful, which I find a big plus. You can even define custom CSS for the preview pane.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/markdown-notes.png&#34; alt=&#34;Markdown notes in VS Code&#34; title=&#34;Markdown notes in VS Code&#34;&gt;
&lt;em&gt;I&amp;rsquo;ve found it very handy for studying&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;source-control&#34;&gt;Source Control&lt;/h2&gt;
&lt;p&gt;This method of file-based notes lends itself to file syncing using e.g. Dropbox or OneDrive, or to version control using something like a private GitHub repository. At the moment I use Dropbox to synchronize Markdown notes between my different machines.&lt;/p&gt;
&lt;h2 id=&#34;drawbacks&#34;&gt;Drawbacks&lt;/h2&gt;
&lt;p&gt;Yes, if you go this route, it isn&amp;rsquo;t really possible to take notes on anything that doesn&amp;rsquo;t run a desktop OS. Also, it doesn&amp;rsquo;t play very nicely with diverse file types, although there are extensions available for viewing things like PDFs.&lt;/p&gt;
&lt;p&gt;Ultimately, though, I&amp;rsquo;ve found that these don&amp;rsquo;t bother me. On the rare occasion I want to note something down while nowhere near a computer, I can just add a quick note using Todoist, Keep, or paper, and transcribe/expand on it at some later point.&lt;/p&gt;
&lt;p&gt;The ability to enter my thoughts quickly using a powerful text editor - and easily search through everything I have notes and ideas on - is worth any inconvenience. I used to get frustrated with my setup and change everything every few months, but so far it&amp;rsquo;s been clear skies and smooth sailing on the HMS Markdown.&lt;/p&gt;
&lt;h2 id=&#34;my-setup&#34;&gt;My Setup&lt;/h2&gt;
&lt;p&gt;I use a folder in Dropbox that is also a VS Code workspace. VS Code allows you to define settings specific to a workspace, and while I tend to prefer reading and writing code in a dark theme, I much prefer a light theme for reading and writing normal text. The workspace contains these settings:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;settings&amp;#34;&lt;/span&gt;: {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;workbench.colorTheme&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Solarized Light+&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;files.exclude&amp;#34;&lt;/span&gt;: {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;**/*.xlsx&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;true&lt;/span&gt;,
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;**/*.docx&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;true&lt;/span&gt;
  },
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;editor.codeActionsOnSave&amp;#34;&lt;/span&gt;: {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;source.fixAll.markdownlint&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;true&lt;/span&gt;
  },
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;markdown.styles&amp;#34;&lt;/span&gt;: [
    &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./.workspace/markdown.css&amp;#34;&lt;/span&gt;
  ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A benefit of including the workspace configuration in your method of synchronization (Dropbox, GitHub, etc.) is that it will look the same on all machines. This can be enhanced by using &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&#34;&gt;Peacock&lt;/a&gt; to give your notes workspace a distinctive colour.&lt;/p&gt;
&lt;p&gt;You will note the inclusion of my custom &lt;code&gt;markdown.css&lt;/code&gt; file, included in the workspace directory (which in this case is within the project root). I find the default Markdown preview a little hard to read, so I added the following extra padding:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;p&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;0.3&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;h1&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;font-weight&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;bold&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;h2&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;1.1&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;font-weight&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;bold&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;h3&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;font-weight&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;bold&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;h4&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;0.8&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;font-weight&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;bold&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;blockquote&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;0.8&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-bottom&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;0.8&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
}

.&lt;span style=&#34;color:#50fa7b&#34;&gt;vscode-body&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;table&lt;/span&gt; {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-top&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;1.2&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
  &lt;span style=&#34;color:#ff79c6&#34;&gt;margin-bottom&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;1.2&lt;/span&gt;&lt;span style=&#34;color:#8be9fd&#34;&gt;em&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Meanwhile, in the User settings (remember to enable &lt;a href=&#34;https://code.visualstudio.com/docs/editor/settings-sync&#34;&gt;Settings Sync&lt;/a&gt;!) I include the following, among many others that are not relevant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;settings&amp;#34;&lt;/span&gt;: {
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;markdown.preview.lineHeight&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;1.45&lt;/span&gt;,
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;markdown.preview.fontFamily&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Roboto Slab&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;markdown.preview.fontSize&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;18&lt;/span&gt;,
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;[markdown]&amp;#34;&lt;/span&gt;: {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;editor.wordWrap&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;on&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;editor.rulers&amp;#34;&lt;/span&gt;: []
  },
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;markdownlint.config&amp;#34;&lt;/span&gt;: {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;MD024&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;false&lt;/span&gt;,
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;MD026&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;false&lt;/span&gt;,
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;MD036&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ff79c6&#34;&gt;false&lt;/span&gt;
  },
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;workbench.colorCustomizations&amp;#34;&lt;/span&gt;: {
    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;[Solarized Light+]&amp;#34;&lt;/span&gt;: {
      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;editorGutter.background&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;#fdf6e3&amp;#34;&lt;/span&gt;
    }
  },
  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;[Solarized Light+]&amp;#34;&lt;/span&gt;: {
      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;textMateRules&amp;#34;&lt;/span&gt;: [
        {
          &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;comment&amp;#34;&lt;/span&gt;,
          &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;settings&amp;#34;&lt;/span&gt;: {
            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;fontStyle&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
          }
        },
        {
          &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;scope&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;punctuation.definition.comment&amp;#34;&lt;/span&gt;,
          &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;settings&amp;#34;&lt;/span&gt;: {
            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;fontStyle&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
          }
        },
      ]
    }
  },
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I keep a &amp;ldquo;Fonts&amp;rdquo; folder in the same place, so that whenever I want to change to a new font, I can easily install it on other machines.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Google Hashcode</title>
      <link>https://eddie-summers.com/projects/google-hashcode/</link>
      <pubDate>Fri, 01 Mar 2019 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/google-hashcode/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;Team Holy Guacamole&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Google HashCode is an annual world-wide team programming competition. I entered it with three friends as team Holy Guacamole in 2019 and 2020.&lt;/p&gt;
&lt;p&gt;The problem in 2019 was to arrange photo objects into slideshows which were most &amp;lsquo;interesting&amp;rsquo;, according to a certain algorithm. Our solution started at the basic level - composing slideshows of photos in the order they were recevied - and advanced to attempting to group photos with popular &amp;lsquo;tags&amp;rsquo; nearer each other, as such groupings were worth more points.&lt;/p&gt;
&lt;p&gt;We wrote our &lt;a href=&#34;https://github.com/Danjb1/google-hashcode-2019&#34;&gt;solution in Typescript&lt;/a&gt;, which was compiled and run on Node. Afterwards, I &lt;a href=&#34;https://github.com/esummers1/hashcode19&#34;&gt;ported our application to Python&lt;/a&gt; and continued to work on it. Since Google provide several input files that have different characteristics, one strategy does not fit all - I designed the Python version to have a bank of strategies with which to group each set of photos, and to choose the most successful strategy for each input file to generate the output solution.&lt;/p&gt;
&lt;p&gt;In 2020, the problem was harder, and revolved around scheduling the scanning of physical books in libraries with different collections. Again, we wrote our &lt;a href=&#34;https://github.com/esummers1/hashcode-2020&#34;&gt;solution(s) in TypeScript&lt;/a&gt; and ran them using Node. While we intended to apply the strategy-selection logic throughout, the problem this year was not easy to model, and we did not have enough time to build a local scoring engine.&lt;/p&gt;
&lt;p&gt;In both cases, we finished in the top 30% of teams worldwide.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Orbit Simulator</title>
      <link>https://eddie-summers.com/projects/orbit-simulator/</link>
      <pubDate>Wed, 16 May 2018 16:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/orbit-simulator/</guid>
      
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/esummers1/orbit-simulator&#34;&gt;Orbit Simulator&lt;/a&gt; is a two-dimensional physics sandbox. It uses a high physics framerate (decoupled from the slower rendering framerate) to compute the orbits of moons, planets and stars using real-world figures at high time accelerations.&lt;/p&gt;
&lt;p&gt;The player can focus the camera on different objects in the simulation, adjust the display scale and time acceleration factor, and &amp;lsquo;fire&amp;rsquo; new objects into the simulation. These new bodies will be created using the average path and velocity of the mouse-drag, meaning they appear seamlessly and intuitively. The other objects in the simulation will feel the gravitational effects of the new object immediately.&lt;/p&gt;
&lt;p&gt;Objects that collide merge into a new object with the combined mass and volume of its parents; its colour will also be an average.&lt;/p&gt;
&lt;p&gt;Orbit Simulator is written in Java and uses Swing for the UI. It can handle highly-accelerated simulation of dozens of bodies without slowdown, though dense objects such as black holes can cause weird behaviour when other objects pass very close.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Hovership</title>
      <link>https://eddie-summers.com/projects/hovership/</link>
      <pubDate>Sat, 13 Jan 2018 20:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/hovership/</guid>
      
      <description>
&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/4cLMlKfPOBY&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Danjb1/hovership&#34;&gt;Hovership&lt;/a&gt; is a simple 3D platforming game with a low-poly art style. I developed it with a friend over the course of a couple of years, meeting once every week or two. It is made using the Unity engine, with code in C#. We created the assets from scratch using Blender, and implemented custom player and camera physics.&lt;/p&gt;
&lt;p&gt;The game has a single level, in which the player must dodge deadly turret fire to collect enough Power Shards to gain the power of flight and be able to find the key which wins the game. This last mechanic was added after the video was made.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Ping</title>
      <link>https://eddie-summers.com/projects/ping/</link>
      <pubDate>Tue, 21 Nov 2017 20:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/ping/</guid>
      
      <description>&lt;p&gt;&lt;a href=&#34;https://github.com/esummers1/ping&#34;&gt;Ping&lt;/a&gt; is an homage to the classic arcade game Pong, with some liberties taken on physics. It appears similar to the original, with two white rectangles for paddles and a white square for a ball.&lt;/p&gt;
&lt;p&gt;The player controls the left paddle, and a rudimentary AI controls the right paddle. The paddle will accelerate and decelerate with a feeling of some weight, rather than just moving up and down linearly. The ball gains speed on each paddle impact, forcing one side to eventually make a mistake. Collisions are implemented by hand, and work most of the time.&lt;/p&gt;
&lt;p&gt;Ping is written in Java and uses Swing for the UI.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Agricultural Capitalism Simulator</title>
      <link>https://eddie-summers.com/projects/agricultural-capitalism-simulator/</link>
      <pubDate>Fri, 18 Aug 2017 16:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/agricultural-capitalism-simulator/</guid>
      
      <description>&lt;p&gt;Agricultural Capitalism Simulator (ACS) is a tongue-in-cheek command-line farming business simulator. The player is given some money and a field, and told to make the greatest amount of profit possible in the allotted number of years. Different crops have different ideal weather conditions, and different fields (which the player can purchase) have different qualities. The weather is generated each game year, producing a certain yield in each field according to its planted crop&amp;rsquo;s characteristics.&lt;/p&gt;
&lt;p&gt;There is also an AI mode, in which a basic evolutionary algorithm with a small set of weightings (probability to plant each crop, and aggressiveness when purchasing new land) optimizes those weightings for high scores. The best strategies from each checkpoint generation will be printed to the player at the terminal.&lt;/p&gt;
&lt;p&gt;ACS was originally &lt;a href=&#34;https://github.com/esummers1/agricultural-capitalism-simulator&#34;&gt;written in Java&lt;/a&gt;; I later &lt;a href=&#34;https://github.com/esummers1/agricultural-capitalism-simulator-py&#34;&gt;ported it to Python&lt;/a&gt;, to practise the language.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>The Lifter&#39;s Manual</title>
      <link>https://eddie-summers.com/projects/the-lifters-manual/</link>
      <pubDate>Fri, 27 Jan 2017 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/projects/the-lifters-manual/</guid>
      
      <description>&lt;p&gt;The Lifter&amp;rsquo;s Manual is a Kindle book I wrote to summarize everything I had learned about lifting weights from my degree, years of coaching clients, and (at the time) ten years of training myself. It is essentially what I wish I could give my 15 year old self.&lt;/p&gt;
&lt;p&gt;It is available on Amazon &lt;a href=&#34;https://www.amazon.co.uk/Lifters-Manual-Build-Always-Wanted-ebook/dp/B01N9XKVVB/ref=sr_1_1?dchild=1&amp;amp;qid=1590253142&amp;amp;refinements=p_27%3AEddie+Summers&amp;amp;s=digital-text&amp;amp;sr=1-1&amp;amp;text=Eddie+Summers&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>The Pyramid of Muscle Gains</title>
      <link>https://eddie-summers.com/articles/fitness/pyramid-of-muscle-gains/</link>
      <pubDate>Sun, 13 Mar 2016 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/pyramid-of-muscle-gains/</guid>
      
      <description>&lt;p&gt;People can get very particular about things that are important to them. I am no exception. But it seems as if nobody gets quite so particular about insignificant details as when it comes to building muscle, being strong and getting leaner.&lt;/p&gt;
&lt;p&gt;This isn’t their fault: the internet is an excellent tool for discovering loads of new information. What’s lacking is a sense of perspective. Newer lifters (and some more experienced ones) lack the framework that gives context to new knowledge. I think it should be obvious to everyone that some things matter more than others – I also think that this framework need not be too complicated. Therefore I present my pyramid of muscle gains:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/gains-pyramid.jpg&#34; alt=&#34;The Pyramid of Muscle Gains&#34; title=&#34;The Pyramid of Muscle Gains&#34;&gt;&lt;/p&gt;
&lt;p&gt;At this point I should point out I’ve never claimed to be a graphic designer.&lt;/p&gt;
&lt;p&gt;My pyramid is made up of mostly trapezoidal bricks stacked in layers (because it’s 2D and easier to draw that way). Each brick contains a factor – a thing you can do or an effort you can make that will move you closer to your goal. Pyramids are collections of layers; each layer stands on a larger one below it. In my universe the level in which the brick is found denotes how important it is: bricks near the top of the pyramid are less important, and bricks near the bottom are more important. This is because each layer is needed for the one above to stand on. Note that this isn’t an exhaustive list of possible factors – the bricks give examples of things of similar relative importance.&lt;/p&gt;
&lt;p&gt;Now as I see it, gaining muscle and accomplishing those associated cool goals are composed of three elements: training, nutrition and recovery. The Pyramid of Muscle Gains is divided into these three sections, and each contributes a brick to each layer. It’s crucial to realize that things you do or efforts you make are &lt;strong&gt;hierarchical&lt;/strong&gt; – some should come before others. That isn’t to say, though, that doing cardio is useless unless you’re sleeping 8 hours per night: what it means is that you get more muscle and strength gains from bigger bricks, so you should take care of those first.&lt;/p&gt;
&lt;p&gt;Something should be obvious to anyone who has spent any amount of time talking to gym bros: a lot of the things people seem to obsess over are towards the top of the pyramid, especially supplements and isolation/accessory exercises. Also note that, in general, the items towards the bottom of the pyramid are things you do more often. That is to say, you sleep more often than you do cardio, and you do cardio more often than you get a massage. When I say things like “lift weights” and “sleep 8 hours/night”, &lt;strong&gt;habit&lt;/strong&gt; is implied. It’s more effective to go to the gym in a simplistic yet consistent manner than to go in a clever yet sporadic manner.&lt;/p&gt;
&lt;p&gt;If I’d thought to do it, the way I would have drawn this pyramid four years ago would probably look different to this one. I’m sure also that in four more years I might draw it another way still, and think I was stupid for ever doing it this way. People I know and work with might well disagree with me over what order I put a few of the bricks in (and I admit the decisions are complex). But the basics will always be the same: consistent hard work that gets harder over time, plus plenty of protein and other calories, plus good rest and cardiovascular health equals the majority of muscle gain. A great way to never progress is to have a workout routine that’s complicated and includes every small exercise you can imagine, prioritize supplements over good food, and not bother about your sleep, stress or cardio.&lt;/p&gt;
&lt;p&gt;The triangle I drew had to be roughly equilateral to be able to fit enough text into it. But the real pyramid of gains – where the area of each brick corresponds to what proportion of muscle gain comes from that factor – would be much wider and much flatter. I estimate 80% of its area would be included within the bottom two rows.&lt;/p&gt;
&lt;h2 id=&#34;practical-message&#34;&gt;Practical Message&lt;/h2&gt;
&lt;p&gt;On your quest to maximize your muscle and minimize your fat – a quest we’re all on ultimately – get yourself organized in the order shown in the pyramid. Get the bottom level sorted first, then the second, and so on. Don’t skip ahead, because it’s inefficient, and there are no prizes for effort. You can worry about the more advanced stuff when you’ve got everything below it nailed. Of course, certain parts of the pyramid rest on assumptions – you can’t lift well or productively if you don’t know how to move properly. You can’t eat enough of each type of nutrient without knowing how much “enough” is. These things are more complicated, and a story for another time.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Lose Fat by Eating More</title>
      <link>https://eddie-summers.com/articles/fitness/lose-fat-by-eating-more/</link>
      <pubDate>Sun, 07 Feb 2016 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/lose-fat-by-eating-more/</guid>
      
      <description>&lt;p&gt;&lt;em&gt;Disclaimer: If all you do is read the title and do what it says, you’ll be in for disappointment. Also, what I write here is not as applicable to people with extreme fat loss goals, e.g. bodybuilders or other physique competitors, at least not towards the end of their preparation. The last vestiges of body fat behave differently to the rest.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For most people, when they feel like they’re getting too soft (or heavy), they’ll instinctively cut food out of their diet. The most common culprits are carbs – especially sugary foods – and fats – often in chocolate or pizza. If you regularly overeat these foods, it’s hard to make the case that you wouldn’t benefit by removing them. But if you don’t tend to binge on “bad” foods, there is a more effective way: eat more.&lt;/p&gt;
&lt;h2 id=&#34;energy-balance&#34;&gt;Energy Balance&lt;/h2&gt;
&lt;p&gt;It’s common knowledge that how heavy you are basically depends on two things: how much energy you take in, and how much you expend. It’s only not a direct relationship because the calorie densities of different tissues – e.g. fat compared to muscle – are different.&lt;/p&gt;
&lt;p&gt;Calorie expenditure is made up of three components:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;BMR – basal metabolic rate, the energy required to keep your body warm and alive while lying down&lt;/li&gt;
&lt;li&gt;TEF – thermic effect of feeding, the energy required to run the processes that extract nutrients from food&lt;/li&gt;
&lt;li&gt;AT – activity thermogenesis*, all the energy you expend in moving around, whether for the sake of exercise or during daily activities&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;*Incidentally, I don’t like this term, because although most of the energy you expend while being active is lost as heat, some of it goes into mechanical work, like moving your body around and lifting things.&lt;/p&gt;
&lt;p&gt;You might have read the term NEAT, which stands for nonexercise activity thermogenesis. This is – probably correctly – praised as the most effective measure for managing obesity. In other words, getting fat people to take the stairs rather than the lift is more effective than trying to get them to go to the gym. “Activity” refers to all the moving you do; “exercise” is activity you do on purpose for the sake of being active.&lt;/p&gt;
&lt;p&gt;A common misconception is that by exercising a lot you can increase your BMR. This is not true, although gaining significant amounts of muscle will increase BMR, as well as the energy cost of all activity. Another common myth, which is particularly annoying, is that some people have “fast” metabolisms and can eat anything they want without gaining weight. These people are often quite skinny. If they weighed their food they would discover the reason they are skinny: they don’t eat as much as they think. If anything, the people with the fastest metabolisms are the very heavy – the ones complaining that they have slow metabolisms. BMR scales strongly with body mass, though it is higher in the very muscular than the very fat, because muscle is more expensive to maintain.&lt;/p&gt;
&lt;p&gt;As an aside – another implication of this is the myth of the “hardgainer”, i.e. someone who can’t seem to eat enough to gain muscle mass. I’ll address this in a later article because it deserves more attention.&lt;/p&gt;
&lt;h2 id=&#34;energy-throughput&#34;&gt;Energy Throughput&lt;/h2&gt;
&lt;p&gt;Here we come to my main point: it’s better to input and output large amounts of energy than small amounts. It’s easy to get drawn into the trap of thinking along these lines – in order to lose fat quickly, I should eat a small amount and do loads of exercise.&lt;/p&gt;
&lt;p&gt;It’s obviously true that it’s necessary to create a caloric deficit to lose fat, but this is easier with a higher intake for two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hunger relates more strongly to &lt;strong&gt;intake&lt;/strong&gt; than to balance&lt;/li&gt;
&lt;li&gt;You can work out harder if you’ve eaten plenty&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you set up a very low-calorie diet, e.g. 1800 kcal/day for an active 80 kg man, it will be difficult to train very hard. You can output more energy in training – which you should want to do because it’ll let you hang on to more muscle as you lose the fat – if you’ve eaten more.&lt;/p&gt;
&lt;p&gt;Most of the time, if someone is on too few calories, increasing their calories without adding any more training will cause them to lose weight faster, as well as feel, look and perform better. This is because the increase in TEF (more food to process) and AT (more energy to work harder) will outweigh the increase in intake. Additionally, referring to point 1, you will be less hungry if you eat more food, even if you actually end up in a bigger deficit than before.&lt;/p&gt;
&lt;p&gt;It’s also worth noting that not all deficits are equal. You may have heard of “starvation mode”, a term referring to the state your body gets into when you eat below maintenance for a long time. Essentially, it values amino acid-containing structures like muscle less highly than it values fat, and you end up losing a disproportionate amount of muscle tissue in order to spare fat. This is broadly true, but it is more complicated.&lt;/p&gt;
&lt;p&gt;Consider also that if your plan is to have a low caloric intake and a modest expenditure, you have nowhere to go. You can’t eat less because you’re already starving yourself, and you can’t do more because you’re tired and hungry all the time. With a high throughput, you have more room to manoeuvre.&lt;/p&gt;
&lt;h2 id=&#34;carbs-and-performance&#34;&gt;Carbs and Performance&lt;/h2&gt;
&lt;p&gt;My final point is on macronutrient ratios. There is more to write about this but in essence, people instinctively cut carbs from their diet. This is a crucial mistake, because having low carbs on a deficit – unless you’re a competitive bodybuilder or similar (as mentioned at the top) – will leave you unable to train at a decent level. Willpower is irrelevant when glycogen is low. Having high glycogen stores is beneficial for other reasons, for example retaining (or even building) more muscle while losing fat. Keep your carbs high enough to have energy to train – don’t fear them just because it was trendy to cut them out in the late 20th century.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;In short, I suggest turning yourself into a furnace – high input of fuel and high output of heat. This is an approach that has worked well for many of my clients (and for me), and has the added benefit of being more fun than the other way. As I’ve said before, I believe in efficiency – partly because being hungry sucks, and partly because unnecessary suffering makes you more likely to quit.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Eat Less Protein to Grow More</title>
      <link>https://eddie-summers.com/articles/fitness/eat-less-protein-to-grow-more/</link>
      <pubDate>Wed, 20 Jan 2016 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/eat-less-protein-to-grow-more/</guid>
      
      <description>&lt;p&gt;How much protein should you eat? This is one of the oldest and most-contested questions in fitness. Classical bodybuilding advice suggests we should eat at least a gram of protein per pound of bodyweight a day. This makes sense at first, seeing as you need protein to build muscle, but the reality is a little more complicated.&lt;/p&gt;
&lt;p&gt;Let’s start with a crude analogy. Let’s say you’re building a house and want to get it finished faster. You have enough materials on-site to keep you going for a while, though not necessarily to finish. Which will let you get it done sooner – getting more materials in now or getting more guys to come and work and buying the rest of the materials later?&lt;/p&gt;
&lt;p&gt;Your body tissues are composed of proteins – we all know this. You can’t build body tissues with carbohydrate and fat because neither of those contain nitrogen atoms. We need nitrogen atoms to build complex, stable structures. Proteins are made of chains of amino acids, small molecules with a carboxyl (carbohydrate-like) group and a nitrogen atom.&lt;/p&gt;
&lt;p&gt;Back at university I remember one of the PhD students in the physiology lab remark that net muscle protein synthesis in healthy men tops out at around 10 grams per day. I’ve since tried to find the source he was referring to, with no luck. However it stands to reason: if you take out fat gain, a typical rate of muscle gain for an unassisted man is a few (1-5) kilos a year. Anything more than 5 is highly unusual, and 5 itself is very high. Five kilos per year represents 13-14 grams per day.&lt;/p&gt;
&lt;p&gt;My point here is that the excess protein mass you need to take on board – because you can’t create matter from nothing and you can’t make amino acids from carbs or fat (not without other amino acids, anyway) – isn’t huge. Certainly the difference between eating 200 g of protein a day and 300 g seems insignificant when the net protein mass needed is on the order of 10 g. Now obviously, this doesn’t account for the fact that protein is being shuttled in and out of body tissues all the time. This is why the RDA of protein for a person not gaining muscle is more than zero grams (!).&lt;/p&gt;
&lt;p&gt;This isn’t just theoretical either – by the end of the 90s we had good data on how much protein is needed by different athletes. The best-known work (to anyone who, like me, has studied sport science) was done by Tarnopolsky (famously in 1992 in JAP), using nitrogen balance, and Lemon’s later review of Tarnopolsky’s and other papers. The upshot of these was that although protein requirements to maintain positive nitrogen balance (more nitrogen staying in the body than leaving) increase with hard exercise, it’s not by as much as people on the internet might think. It’s worth noting there has never been a dose-response relationship shown between nitrogen balance and muscle protein synthesis: i.e. more intake above the requirement for positive balance doesn’t increase rate of muscle gain. Interestingly, hard endurance exercise increases protein needs by nearly as much as bodybuilding does. For both, the maximum needs reported are under 1.6-1.7 g/kg per day. The old recommendation of 1 g/lb per day isn’t far off, as that would be 2.2 g/kg per day.&lt;/p&gt;
&lt;p&gt;There are problems with nitrogen balance as a measure, but it serves our purpose well enough if we add a safety margin on. If we recommend 1.8 g/kg per day for anyone who lifts weights, we’re recommending plenty. This is especially generous when you consider that whenever needs as high as 1.6-1.7 g/kg per day have been reported, it’s with huge training loads – 12+ hours of hard endurance or resistance training per week by trained athletes. These loads are definitely higher than those performed by recreational bodybuilders or gym rats, who would therefore need even less.&lt;/p&gt;
&lt;p&gt;Another aspect to protein that’s overlooked is its inefficiency as a fuel. This is a double-edged sword. Briefly, the uric acid cycle is a process that runs in tandem with the Krebs cycle, the cycle that makes most of the energy in muscle: products from one enter the other and vice-versa, although they occur in different tissues. Nitrogen is unreactive, which makes it hard to remove from wherever it is. It’s therefore difficult to turn an amino acid molecule into a carbohydrate/fat-like molecule (acetyl coenzyme A, for use in the Krebs cycle) that’s useful for fuel. This is why dietary protein contains 6-8 kcal/g but we can only extract 4 kcal/g at best. If you eat large amounts of protein, the body has to get rid of lots of nitrogen – this is the basis of the pervasive bad-for-your-kidneys myth. This isn’t true, but it is true that you’re wasting calories from other food you eat in order to process any protein over your structural requirements.&lt;/p&gt;
&lt;p&gt;Protein is also filling, and difficult to eat lots of. For this reason it’s great to eat lots of protein on a caloric deficit – especially because the increased protein helps you hang on to muscle as you lose fat – and a bad idea to eat lots during a surplus. To return to our worker/materials analogy, building new tissue requires raw materials and lots of energy. It’s more efficient to get this energy from other nutrients: namely carbs and fat. It’s easy to eat loads of calories in carbs and fat, and no more effective to eat them in extra protein instead, so make it easy for yourself. It also makes sense with our 1.8 g/kg figure: as you increase your intake of calories, your protein intake stays the same, because it’s scaled to bodyweight. If you weigh 100 kg, you’ll eat 180 g of protein a day whether you’re eating 2800 calories, to lose fat, or 4000, to gain muscle (numbers are approximate). All of those 1200 extra calories therefore come from carbs and fat.&lt;/p&gt;
&lt;p&gt;A final word on protein supplements – it is true that research has found the existence of an “anabolic window” after resistance training, during which protein consumption has a strong effect on muscle protein synthesis. However this window is 48 hours long, not 30-90 minutes, and nobody who goes to the gym has more than two days’ gap between meals. Particular benefits of protein shakes, rather than foods containing protein, haven’t been established, other than being convenient. Convenience is enough reason for me to use them – it’s hard to cook a steak at the gym, and if you’re on a surplus you need all the chances you can to cram in more food.&lt;/p&gt;
&lt;h2 id=&#34;practical-message&#34;&gt;Practical Message&lt;/h2&gt;
&lt;p&gt;Ultimately my point is that it’s difficult to eat enough to grow consistently. It’s especially hard if you stick to a dogmatic view of protein. If by reducing your relative protein intake (to ~1.8 g/kg/day) you can eat more total calories, you lose nothing and make more gains. And if I care most about two things, they’re getting more for your effort and making more gains.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Get Strong to Get Big</title>
      <link>https://eddie-summers.com/articles/fitness/get-strong-to-get-big/</link>
      <pubDate>Wed, 02 Dec 2015 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/get-strong-to-get-big/</guid>
      
      <description>&lt;p&gt;In my opinion, the best way for most people to gain muscle size is to train mainly for strength. Note that I say most people – for people who are already fairly strong, it’s very useful to incorporate more bodybuilding-style exercises to provide extra stimulus to the right muscles. However even for them, the majority of what makes them grow bigger is lifting heavy weights for large volumes.&lt;/p&gt;
&lt;p&gt;My argument for this is simple. If we agree that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lifting a lot of weight lots of times is the stimulus for growing big muscles&lt;/li&gt;
&lt;li&gt;Being stronger allows us to lift more weight&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should be clear that being stronger enables the training you do to stimulate more growth. Let’s take a closer look.&lt;/p&gt;
&lt;p&gt;The basic structure we deal with here is the muscle-tendon unit: an organ which produces tension between two or more bones when a neural command is sent. These commands are sent to motor units, groups of fibres which obey the orders of a single motor neuron. The unit has a maximum possible force output under normal conditions, e.g. not when under adrenal boost. The same unit can&amp;rsquo;t output more force without growing – but can recruit more, because the nervous system can’t voluntarily order 100% of all motor units to contract. There is room to improve.&lt;/p&gt;
&lt;p&gt;An adaptation to lifting heavy weights is that the neural connections to the muscles that have been trained become able to recruit a higher proportion of the motor units at one time. This means a muscle which is structurally the same – no thicker or denser – can produce more force.&lt;/p&gt;
&lt;p&gt;The key thing to realize here is that this makes outputting maximum voluntary force &lt;strong&gt;harder&lt;/strong&gt; for the muscle. If you can squat 100 kg because you do 75 kg for sets of 10, then start going much heavier – handling weights around 90 kg – you might well drive your max up to 120-130 kg without getting a great deal bigger. You certainly won’t have got 20-30% bigger.&lt;/p&gt;
&lt;p&gt;But wait – your muscles aren’t physically much different to how they were when you could only move 100 kg. Now you can move 120 kg, which means you can do 100 kg for sets of five instead of only a max. This is much more stressful to the fabric of the muscle, because you’re doing loads more work. Getting stronger has increased your working weight and made your training harder, which makes the stimulus for growth – repeated heavy loading – bigger. Now when you do your fives at 100 or so, you’ll grow your leg and hip muscles more dramatically. This will set you up to make new neural adaptations to make better use of this new muscle tissue. It’s a circular process. If you are afraid of staying small because you don’t get a pump when you train, you’ll only ever cover half the cycle and will gain less than you could.&lt;/p&gt;
&lt;p&gt;Without going too deep into real numbers, from my experience training novices in the gym I think most new people aren’t strong enough to really fatigue themselves unless they keep the reps low. Now I know my example about the squat was contrived – it doesn’t really work like this. But the way it does work is that people who do sets of few enough reps to handle a challenging weight progress far more rapidly than those who don’t. And although fives may not build as much muscle as classic sets of 8-12, lifting light weights builds less muscle than lifting heavy weights.&lt;/p&gt;
&lt;p&gt;The reason 5×5 programmes are popular is that they are the best compromise between using more weight and doing more reps.&lt;/p&gt;
&lt;h2 id=&#34;practical-message&#34;&gt;Practical Message&lt;/h2&gt;
&lt;p&gt;Let’s be real for a moment. If you’re an adult man weighing at least 70 kg and you bench press less than 100 kg you have no need for a chest day where you do a bunch of different dumbbell isolation exercises, even if the only thing you want is big arms/pecs/shoulders. What you need is to do 5×5 on just bench press twice a week (rowing an equal amount, of course) until you can bench 100 kg. You can do extra stuff if you like – just get that in first. Once you can handle those bigger weights, you’ll be surprised how much more effective doing incline dumbbell press, flyes, etc. becomes.&lt;/p&gt;
&lt;p&gt;Stick to the basics first and get strong, because this lets you skip ahead. It isn’t a coincidence that all the biggest guys are strong, and all the strongest guys are big. You use strength to drive size to drive strength.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>How to Warm Up Better for Bigger Lifts</title>
      <link>https://eddie-summers.com/articles/fitness/warm-up-better-for-bigger-lifts/</link>
      <pubDate>Wed, 22 Jul 2015 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/warm-up-better-for-bigger-lifts/</guid>
      
      <description>&lt;p&gt;We all know warming up before exercise is important. A good warm up will reduce risk of injury and improve performance. However, it is easy to get carried away doing too much mobility and activation work before loading a barbell. We want to get the maximum benefit with minimal time spent. This will involve doing three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remove movement restrictions&lt;/li&gt;
&lt;li&gt;Prime key muscles&lt;/li&gt;
&lt;li&gt;Increase body temperature&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;remove-movement-restrictions&#34;&gt;Remove Movement Restrictions&lt;/h2&gt;
&lt;p&gt;The nature of this step will depend on your particular level of function at rest. Can you, having sat for two hours, get up and sink into a full squat with your heels on the floor and your knees out? If so, you can probably skip this step.&lt;/p&gt;
&lt;p&gt;It is a cliché by now that we as humans who sit at desks and in cars have chronically shortened hip flexors and hamstrings, as well as flexed thoracic spines and extended cervical spines. This manifests as tight, stiff hips and rounded shoulders. To squat, deadlift, press or bench press effectively, these will need to be alleviated. It is often enough to squat down with your back against something solid and spend 30 seconds or so prying your knees out and opening your hips. Ideally you would avoid actual soft-tissue work like foam rolling or tissue smashing before training.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/warmup1.jpeg&#34; alt=&#34;Anterior band distraction&#34; title=&#34;Anterior band distraction&#34;&gt;&lt;/p&gt;
&lt;p&gt;A favourite drill of mine to supplement this is to use a band to apply an anterior hip distraction. This looks like a traditional psoas-quad stretch but, since muscles are both stronger and stiffer than we give them credit for, we use the band tension to create some extra space in the hip joint. This can help reduce the tight or impacted feeling we get in our hips. It will also help you hit depth on the squat and get into a good starting position when you deadlift. Make sure you flex your rectus abdominis (or six-pack muscle) and glutes to tilt the pelvis backwards and magnify the stretch. If you don’t do this you can lunge forwards without lengthening the hip flexors at all.&lt;/p&gt;
&lt;p&gt;For people who also feel tight and hunched through the thoracic spine, I suggest lying on something like a foam roller and stretching backwards over it: starting at the top of your back and keeping your hips on the floor with your chin tucked in, touch the back of your head to the floor. Do this with the foam roller all the way down your spine, getting as much of your back in contact with the floor as you can at each stage. This, combined with the anterior hip distraction and some prying in the bottom of a squat, should leave you ready to adopt the proper positions.&lt;/p&gt;
&lt;h2 id=&#34;prime-key-muscles&#34;&gt;Prime Key Muscles&lt;/h2&gt;
&lt;p&gt;The next step is to choose one or two muscle groups which are key to tying the movement together. For example, since your glutes connect the lats and thoracolumbar fascia to the hamstrings and rest of the kinetic chain, as well as posteriorly rotating your pelvis and providing strong hip extension, it makes sense for us to prime them for work before squatting or deadlifting. You can accomplish this using pre-activation exercises: these are drills derived from physiotherapy, in which you use an external resistance to help you develop more tension in a muscle. Our purpose is to cue them to contract more in the pattern we want to perform: for this reason my favourite glute activator is the banded goblet squat.&lt;/p&gt;
&lt;p&gt;To perform this, take either a short band or double over a standard-length red band. Loop it around your legs, just above your knees. Grab some kind of weight between 10 and 20 kilos and hold it close to your chest. Adopt your squat stance, and twist your feet into the floor as if to turn your toes outwards. Your feet shouldn’t move, and you should feel friction build up. Your glutes will also activate more strongly. Now, squat down, driving your knees out against the band. On the way back up, push your hips through as if finishing a deadlift.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/warmup2.jpeg&#34; alt=&#34;Goblet squat top position&#34; title=&#34;Goblet squat top position&#34;&gt;
&lt;img src=&#34;https://eddie-summers.com/images/warmup3.jpeg&#34; alt=&#34;Goblet squat bottom position&#34; title=&#34;Goblet squat bottom position&#34;&gt;&lt;/p&gt;
&lt;p&gt;Similarly, during the press and bench press, the muscles which retract and rotate the scapula are critical both for keeping the shoulder socket moving correctly and for transmitting power into the bar. A good way to switch these on is to take a band, hold it in front of you at arm’s length, and pull it as if to make it longer. You can adjust the resistance by using a thicker band or by gripping with your hands closer together.&lt;/p&gt;
&lt;h2 id=&#34;increase-body-temperature&#34;&gt;Increase Body Temperature&lt;/h2&gt;
&lt;p&gt;This last step is the simplest, and we can do it nearly by accident. Once you’ve removed your restrictions and activated latent key muscles, the next task is to begin grooving the movement with the bar. Stick with the bar only for a couple of sets, then add some weight (e.g. 60 kg) to begin ramping up activation of your prime movers. If you don’t pause much between these few sets, you’ll probably be sweating long before your work weight.&lt;/p&gt;
&lt;p&gt;Let’s look at a sample of a series of warm-ups I would take. For example, let’s assume I want to bench press 125 kg for 5×2. This is not a max attempt, so I will be less sparing with volume on the warm-up. I’d start with the bar for two sets of 8-10, then 60 kg for 5, 80 kg for 5, 100 kg for 4, 110 kg for 3, 120 kg for 2. If this were a lighter weight, e.g. a 4×8 load, I might do 4-5 reps through each warm-up weight. The goal is to do only enough sets to prepare your technique for executing the weight you aim to lift. If you use sets of 5 throughout when warming up for a one-rep max, you will be too fatigued to hit full performance. An example warm up series for a maximum squat attempt could be: bar for 2×8, 60 kg for 5, 100 kg for 3, 140 kg for 2, 180 kg for 1, 195 kg for 1, 205 kg attempt. If you are not happy with each rep at each new weight, re-attempt the weight until you are.&lt;/p&gt;
&lt;p&gt;The flip side to this advice is that adding more reps during the warm-up, especially on high-volume or hypertrophy-focused sessions, is an easy way to accumulate more tonnage and make your training more productive.&lt;/p&gt;
&lt;p&gt;A final thought is to consider where you put your mobility work, e.g. mobilizing, stretching, tissue smashing. Everyone needs some maintenance, and many of us need drastic work on our movement ranges. However, the time to do this is either after training or on your off days. Think of the goal of this mobility work as being to reduce the amount of time you need to spend warming up. Your aim should ultimately be to arrive at the gym, go over to the bar and start lifting it.&lt;/p&gt;
</description>
      
    </item>
    
    <item>
      <title>Body Proportions and Lifting Talent</title>
      <link>https://eddie-summers.com/articles/fitness/body-proportions-and-lifting-talent/</link>
      <pubDate>Wed, 08 Jul 2015 18:00:00 +0000</pubDate>
      
      <guid>https://eddie-summers.com/articles/fitness/body-proportions-and-lifting-talent/</guid>
      
      <description>&lt;p&gt;Some people will always be better at some movements than others, even when training histories are taken into account. Your body’s proportions can predict which movements you will be better at: here’s why.&lt;/p&gt;
&lt;p&gt;Let’s look at squat and deadlift mechanics. In both, you must generate hip and knee extension and transmit these forces to the bar. Deadlifting large weights is inefficient because your knees and shins are in the way of the bar. Compare the two photos below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://eddie-summers.com/images/deadlift1.jpg&#34; alt=&#34;Conventional deadlift&#34; title=&#34;Conventional deadlift&#34;&gt;
&lt;img src=&#34;https://eddie-summers.com/images/deadlift2.jpg&#34; alt=&#34;Dumbbell deadlift&#34; title=&#34;Dumbbell deadlift&#34;&gt;&lt;/p&gt;
&lt;p&gt;In the second photo I am holding dumbbells at the same height as the barbell. Notice that my hips are lower and my knees are more flexed. This is a stronger position, and is analogous to the top half of a squat. It is stronger because the relative contributions to overall extension torque are more even between the knee and hip. It doesn’t take much experience in gyms to know that people can half-squat a lot more than they can squat or deadlift. Using a trap-bar for deadlifting – a common practice in training non-strength athletes – changes the setup position to look more like the second photo.&lt;/p&gt;
&lt;p&gt;When deadlifting with a barbell your shins must stay closer to vertical and, therefore, your hips must start higher. These two factors shift the majority of demand for extension torque to the hip: for this reason, deadlifting favours a short back relative to height. Conversely, in the squat, a long back and short legs mean the lifter is able to keep a more upright back and minimize its horizontal length. This is only an option when deadlifting if you use a trap-bar.&lt;/p&gt;
&lt;p&gt;Interestingly, since taller people tend to have a larger proportion of their height in their legs, this means tall people tend to be good deadlifters (despite the extra distance required) and short people tend to be good squatters. This also makes powerlifting a well-balanced sport, in that being built well for squatting (short limbs, long back) makes you worse at deadlifting. Also, the better-built you are for bench pressing – with a large torso and short arms – the worse you will be at deadlifting. The reverse is true in both cases.&lt;/p&gt;
&lt;p&gt;Now, since altering your limb lengths is impractical, this largely determines exercise selection. If you are not training for a barbell sport and you are built poorly for deadlifting (like me), it might be wise to choose an alternative such as Romanian deadlifts with lighter weights or trap-bar deadlifting. The reason for this is that under heavy loads, a person with a long spine will find it hard to stay neutral: the body instinctively tries to reduce the back’s effective length by rounding it. The same goes for squats: it may be more productive to box squat instead, for example.&lt;/p&gt;
&lt;p&gt;If you train for powerlifting and want to deadlift the most weight, experiment with sumo and conventional. If you find it hard to keep your spine neutral due to its length, sumo may be a better lift than conventional, simply because it has a more upright (squat-like) start position. However, ultimately you should train both and compete using the more comfortable one.&lt;/p&gt;
&lt;p&gt;The final word of advice I have is to play to your strengths. If your proportions favour one lift over the other, you will find it easier to accumulate training volume on that lift. Both squat and deadlift produce large stimuli for whole-body growth, and as long as you do at least some work on the one you are worse at (or something like it) you won’t go far wrong.&lt;/p&gt;
</description>
      
    </item>
    
  </channel>
</rss>
