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

  <title>Matt Newman</title>
  <link href="/feed/category/software-tech/" rel="self"/>
  <link href="/"/>
  <updated>2026-04-09T22:33:26+00:00</updated>
  <id>/feed/category/software-tech/</id>
  <author>
    <name>Matt Newman</name>
  </author>

  
  <entry>
    <title>Travel posts</title>
    <link href="/2018/06/travel-posts/"/>
    <updated>2018-06-16T00:00:00+00:00</updated>
    <id>/2018/06/travel-posts/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;Sometime in the next couple of days I’m going to publish a bunch of back dated
posts about travel I’ve done recently (or in some cases not so recently). A lot
of these posts are taken straight from emails I sent to family and friends at
the time I did the actual travel, I decided to post them here as &lt;a href=&quot;https://www.hanselman.com/blog/DoTheyDeserveTheGiftOfYourKeystrokes.aspx&quot;&gt;email is
where keystrokes go to
die&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is a bit of a departure from what has been the norm on this blog so far,
and for those following via RSS I’ve introduced categories and separate feeds
for the &lt;a href=&quot;/feed/category/software-tech/&quot;&gt;Software/Tech&lt;/a&gt;
category and the &lt;a href=&quot;/feed/category/travel/&quot;&gt;Travel&lt;/a&gt;
category in addition to the &lt;a href=&quot;/feed/&quot;&gt;existing feed containing all posts&lt;/a&gt;.  If you’d rather not hear about travel posts, please update
your subscription :)&lt;/p&gt;

&lt;p&gt;Technically, the only interesting part of this is handling the images I wanted
to include in the posts. I’ve included a few images in the past, but never in a
large quantity.&lt;/p&gt;

&lt;p&gt;I use Google Photos/Drive for all my photos, and originally tried
hotlinking the photos from there. If this was supported it would have been the
best solution, as I wouldn’t have to duplicate the photos and it would be easy
to include them (though some of them are quite large). Unfortunately (though
unsurprisingly) Google Photos/Drive doesn’t support hotlinking, and any direct
links to images expire after a while.&lt;/p&gt;

&lt;p&gt;The next option was using the Google Drive ‘embed’ functionality, which
involves inserting some HTML into the post which will load an IFrame. This
worked, but:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it looked a little clunky on desktop and didn’t scale well on mobile&lt;/li&gt;
  &lt;li&gt;a Google IFrame means Google tracking cookies&lt;/li&gt;
  &lt;li&gt;performance was poor - loading all the images on one of the travel posts
using this method resulted in a whole load of extra requests:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2018/06/google-drive-iframe-performance.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2018/06/google-drive-iframe-performance.png&quot; alt=&quot;&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;I ended up committing them into the Git repository that backs this static site,
but that does mean the repo size is going to grow a lot more than it should. As
it’s just me working on this repo though, I can always use &lt;a href=&quot;https://git-scm.com/docs/git-filter-branch&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
filter-branch&lt;/code&gt;&lt;/a&gt; as a last resort if
I do want to move the images elsewhere. To avoid bloating the repo too much and
to keep loading times low I did fairly aggressively reduce the file size with
ImageMagick:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mogrify -sampling-factor 4:2:0 \
  -strip \
  -quality 85 \
  -interlace JPEG \
  -colorspace sRGB \
  -resize 50% \
  -auto-orient
  *
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The final change was adding lazy loading using &lt;a href=&quot;https://github.com/ApoorvSaxena/lozad.js&quot;&gt;Lozad.js&lt;/a&gt;. Thankfully I
include almost all the images on my site using a &lt;a href=&quot;https://github.com/mdjnewman/mdjnewman.github.io/blob/master/_includes/figure.html&quot;&gt;custom Jekyll
include&lt;/a&gt; so I just had to include the library and change one
file to get lazy loading across the board.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Vetted - tweaking importer performance</title>
    <link href="/2018/03/vetted-tweaking-importer-performance/"/>
    <updated>2018-03-03T00:00:00+00:00</updated>
    <id>/2018/03/vetted-tweaking-importer-performance/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;Since the &lt;a href=&quot;/2018/01/vetted-importing-data/&quot;&gt;last post&lt;/a&gt;, I’ve started working on
an importer to load data from the existing Access database. Work to date is on
&lt;a href=&quot;https://github.com/mdjnewman/vetted/tree/f1253732f1c2e582fd6412a45aa75a133fa8bb78&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the current domain model, there is a single aggregate root, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Client&lt;/code&gt;.
The importer is written as a command line application which interacts directly
with the domain, assuming an empty database (I might get to incremental imports
in the future). At a high level, the importer currently:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Creates the clients&lt;/li&gt;
  &lt;li&gt;Adds any existing ‘notes’ about the client
    &lt;ul&gt;
      &lt;li&gt;Notes are freeform text about a client, unrelated to any particular patient or
transaction&lt;/li&gt;
      &lt;li&gt;The existing application is a little limited in what can be entered into
the main form, so notes have been used to make up the slack (e.g. in the
existing data, there are numerous clients which have an email address or fax
number in the notes field, as there is no first class input for these values)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Adds home and mobile phone numbers&lt;/li&gt;
  &lt;li&gt;Adds the ‘most common travel distance’ as a note&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These steps are visible in the implementation of the importer:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vararg&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;accessDb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clientTableRows&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;newClientIds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createClients&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;accessDb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;postCodeFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;accessDb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stateFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;commandGateway&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;allOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;addClientNotes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newClientIds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commandGateway&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;addPhoneNumbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newClientIds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commandGateway&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;addMostCommonDistance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newClientIds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commandGateway&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, clients are created, producing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Map&lt;/code&gt; of the old client ID to the new
client ID. Once all clients have been created, all the other updates are
applied (potentially concurrently).&lt;/p&gt;

&lt;p&gt;Without giving away too much information about the existing data, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Order_of_magnitude&quot;&gt;order of
magnitude&lt;/a&gt; of the existing number of clients is 3, and the total number
of events generated with the current importer implementation is at most 5x the
number of clients (one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientMigratedEvent&lt;/code&gt;, up to two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientNoteAddedEvent&lt;/code&gt;s
and up to two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientPhoneNumberAddedEvent&lt;/code&gt;s).&lt;/p&gt;

&lt;p&gt;My first pass at the importer was taking around 80 seconds to import everything
into a PostgreSQL database. I know that &lt;a href=&quot;http://wiki.c2.com/?PrematureOptimization&quot;&gt;premature optimization is the root of
all evil&lt;/a&gt;, and that I don’t have anything resembling a
working product at the moment, but this seemed far too high. Also, it was
impacting my ability to iterate quickly with ‘production’ data, which is enough
of a reason to look for improvements.&lt;/p&gt;

&lt;p&gt;After looking at the generated schema and doing some sampling with
&lt;a href=&quot;https://visualvm.github.io/&quot;&gt;VisualVM&lt;/a&gt;, I decided there were three options to investigate:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Asynchronous processing of commands&lt;/li&gt;
  &lt;li&gt;Serialisation format changes&lt;/li&gt;
  &lt;li&gt;Generated schema changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to compare a full run of the importer pre and post optimisations, I
want to be able to toggle the optimisations on/off from the command line. The
following script has the toggle properties in place, and in the sections below I
will use Spring config management to read these properties.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PASSWORD=$(uuidgen)

docker stop vetted-postgres ; docker rm vetted-postgres

docker run \
    --publish 5432:5432/tcp \
    --name vetted-postgres \
    --env POSTGRES_PASSWORD=$PASSWORD \
    --detach \
    postgres

./gradlew build

java \
    -jar importer/build/libs/vetted-importer-0.0.1-SNAPSHOT.jar \
    --axon.use-async-command-bus=false \
    --axon.use-cbor-serializer=false \
    --spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect \
    --spring.datasource.password=$PASSWORD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The script above will allow me to evaluate the impact of any changes I make in
a repeatable fashion.&lt;/p&gt;

&lt;h2 id=&quot;option-1---asynchronous-processing-of-commands&quot;&gt;Option 1 - Asynchronous processing of commands&lt;/h2&gt;

&lt;p&gt;I’m using the &lt;a href=&quot;http://www.axonframework.org/&quot;&gt;Axon framework&lt;/a&gt;, which handles a lot of the plumbing of
building an application based on DDD &amp;amp; CQRS principles. By default when using
the Spring auto-configuration, a &lt;a href=&quot;https://github.com/AxonFramework/AxonFramework/blob/fd88dfe/messaging/src/main/java/org/axonframework/commandhandling/SimpleCommandBus.java&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleCommandBus&lt;/code&gt;&lt;/a&gt; is used
which processes commands on the calling thread.&lt;/p&gt;

&lt;p&gt;I added some configuration to use a &lt;a href=&quot;https://github.com/AxonFramework/AxonFramework/blob/fd88dfe/messaging/src/main/java/org/axonframework/commandhandling/AsynchronousCommandBus.java&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsynchronousCommandBus&lt;/code&gt;&lt;/a&gt;
with a configurable number of threads:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;@Bean
@ConditionalOnProperty(
    value = [&quot;axon.use-async-command-bus&quot;],
    matchIfMissing = true
)
fun bus(
    transactionManager: TransactionManager,
    @Value(&quot;\${axon.command-bus.executor.pool-size}&quot;) poolSize: Int
): CommandBus {
    val bus = AsynchronousCommandBus(
        Executors.newFixedThreadPool(poolSize)
    )

    val tmi = TransactionManagingInterceptor(transactionManager)
    bus.registerHandlerInterceptor(tmi)

    return bus
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I initially tried this configuration out with a pool size of 10. This reduced
the time for the import to around 30 seconds, which is an improvement from 80
seconds but short of an order of magnitude improvement which should be
possible. This led me to believe that there was either contention somewhere
else, or that some of the constant factors are just too high at the moment.&lt;/p&gt;

&lt;h2 id=&quot;option-2---serialisation-format-changes&quot;&gt;Option 2 - Serialisation format changes&lt;/h2&gt;

&lt;p&gt;By default, Axon will use &lt;a href=&quot;https://x-stream.github.io/&quot;&gt;XStream&lt;/a&gt; to serialise
events, which uses an XML representation. XML is quite verbose, and the &lt;a href=&quot;https://docs.axonframework.org/part4/performance-tuning.html#different-serializer-for-events&quot;&gt;Axon
documentation&lt;/a&gt; even suggests using a different
serializer.&lt;/p&gt;

&lt;p&gt;Overriding the serializer is thankfully quite easy:&lt;/p&gt;

&lt;div class=&quot;language-kotlin highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Primary&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Bean&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@ConditionalOnProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;axon.use-cbor-serializer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;matchIfMissing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;serializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Serializer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;py&quot;&gt;objectMapper&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ObjectMapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;CBORFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;objectMapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;findAndRegisterModules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;objectMapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setSerializationInclusion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NON_ABSENT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JacksonSerializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectMapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I opted for using &lt;a href=&quot;https://github.com/FasterXML/jackson&quot;&gt;Jackson&lt;/a&gt; with a ‘Concise Binary Object
Representation’ (CBOR) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JsonFactory&lt;/code&gt;. This resulted in a ~70% reduction in size
for the serialized payload for most events. With XML:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;postgres=# select avg(length(loread(lo_open(payload::int, x&apos;40000&apos;::int), x&apos;40000&apos;::int))) from domain_event_entry;
     avg
--------------
 433.69003053
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and with CBOR:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     avg
--------------
 111.54379774
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This didn’t have a huge impact on the run time of the importer, but is still a
worthwhile optimisation.&lt;/p&gt;

&lt;h2 id=&quot;option-3---generated-schema-changes&quot;&gt;Option 3 - Generated schema changes&lt;/h2&gt;

&lt;p&gt;You may have noticed in the SQL statments above that the current schema is
using the PostgreSQL &lt;a href=&quot;https://www.postgresql.org/docs/10/static/largeobjects.html&quot;&gt;large objects&lt;/a&gt; functionality. From the
PostgreSQL docs:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;PostgreSQL has a large object facility, which provides stream-style access
to user data that is stored in a special large-object structure. Streaming
access is useful when working with data values that are too large to
manipulate conveniently as a whole.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we inspect the schema that’s being generated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;postgres=# \d domain_event_entry
     Table &quot;public.domain_event_entry&quot;
      Column      | Type | Nullable | Default
------------------+------+----------+---------
 meta_data        | oid  |          |
 payload          | oid  | not null |
 ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oid&lt;/code&gt; type here is an &lt;strong&gt;o&lt;/strong&gt;bject &lt;strong&gt;id&lt;/strong&gt;entifier - a reference to a large
object which is stored externally from the table. The events we’re writing are
small enough that the overhead of reading them as separate streams is hurting
performance rather than helping.&lt;/p&gt;

&lt;p&gt;At least two people have had the same issue when using Axon with PostgreSQL, as
evidenced by the questions on &lt;a href=&quot;https://groups.google.com/forum/#!msg/axonframework/PfzLa3hBR0Y/nsie2H8kPP8J&quot;&gt;Google Groups&lt;/a&gt; and
&lt;a href=&quot;https://github.com/AxonFramework/AxonFramework/issues/445&quot;&gt;StackOverflow&lt;/a&gt;. The suggestion to customise the PostgreSQL
dialect used by Hibernate seems to work, and further reduced the runtime to
around 8 seconds.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Based on my very rough benchmarking, the three changes above have reduced the
run time of the importer from around 80 seconds to 8 seconds. The code
is all at the link above, and the optimisations are on by default.&lt;/p&gt;

&lt;p&gt;There is surely more that can be done to improve performance, but that’s fast
enough for now!&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Vetted - importing data into an event sourced system</title>
    <link href="/2018/01/vetted-importing-data/"/>
    <updated>2018-01-30T00:00:00+00:00</updated>
    <id>/2018/01/vetted-importing-data/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href=&quot;/2017/11/vetted-a-new-hope/&quot;&gt;Vetted - a new project&lt;/a&gt; for some background.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A task I’m going to have to tackle sooner or later is importing data from the
existing Access database. As I’m going to try my hand at event sourcing, this
raises an interesting question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Given an existing application with data stored in an relational database &amp;amp; no
notion of events, how do you go about importing data into an event sourced
system?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;options&quot;&gt;Options&lt;/h2&gt;

&lt;p&gt;At a high level, the initial options seem to be:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Try to reverse engineer/map the existing state to events&lt;/li&gt;
  &lt;li&gt;Have some sort of migration event event in your domain model (e.g.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FooMigrated&lt;/code&gt;) which acts as a snapshot&lt;/li&gt;
  &lt;li&gt;Run everything through your new API as commands, and allow the API
implementation to take care of creating the relevant events like normal&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;recreating-domain-events&quot;&gt;‘Recreating’ domain events&lt;/h3&gt;

&lt;p&gt;Option one above would be nice, but seems impractical at best and is more likely
impossible. For every domain object (client, patient, payment, invoice,
vaccination etc) I’d need to try and reverse engineer the real-world happenings
that occurred to transition the object into its current state.&lt;/p&gt;

&lt;h3 id=&quot;a-migration-event-as-a-snapshot&quot;&gt;A ‘migration event’ as a snapshot&lt;/h3&gt;

&lt;p&gt;Originally when a colleague suggested this it conflicted with my understanding
of the term ‘snapshot’. To me a ‘snapshot’ has always been about collapsing an
event stream into a single event for performance reasons. When using this kind
of snapshot, the original stream of events is still available.&lt;/p&gt;

&lt;p&gt;The second kind of snapshot (which I didn’t see immediately) is a snapshot
which is used as base data. When using a snapshot as base data, the collapsed
state of the aggregate at the time the snapshot is all the information you have
about the history of the aggregate.&lt;/p&gt;

&lt;p&gt;It could also be argued that the migration is a meaningful domain event in its
own right, and should be captured explicitly. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomerMigratedEvent&lt;/code&gt; could
result in the creation of a new customer aggregate root in the same way that a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CustomerRegisteredEvent&lt;/code&gt; does.&lt;/p&gt;

&lt;h3 id=&quot;run-all-existing-data-through-the-new-api&quot;&gt;Run all existing data through the new API&lt;/h3&gt;

&lt;p&gt;It should be possible to write a script that reads data from the existing
database, creates commands and posts those to the appropriate API. The relevant
events would ultimately be created off the back of processing the commands, so
all ‘legacy’ data should look exactly the same as anything created going
forward.&lt;/p&gt;

&lt;p&gt;The outcome is probably close to option one above, but with less manual work.&lt;/p&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;

&lt;p&gt;So far I’ve been spending a lot of time on the technical concepts &amp;amp; design of
an event sourced system, without doing much on the implementation side.&lt;/p&gt;

&lt;p&gt;It’s hard to build a useful conceptual domain model without considering
implementation issues, so I think it’s time I stopped debating concepts and
wrote some code.&lt;/p&gt;

&lt;p&gt;I’m planning to explore a little and gain an understanding of how building and
executing commands would differ in practice from the ‘import event’ option
above.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://groups.google.com/forum/#!topic/dddcqrs/xUbKn8YLJfk&quot;&gt;Importing historic data into an Event Store&lt;/a&gt; on the DDD/CQRS Google Group&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/43640256/importing-data-and-event-sourcing&quot;&gt;Importing data and Event Sourcing&lt;/a&gt; on Stack Overflow&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://martinfowler.com/eaaDev/EventSourcing.html&quot;&gt;Event Sourcing&lt;/a&gt; on martinfowler.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;

&lt;p&gt;Thanks to Roman Safronov, Chris Rowe, Martin Fowler, Mariano Giuffrida, Jim
Barritt and Nouman Memon for taking the time to reply and/or chat about event
sourcing! Any good ideas are theirs, and errors are mine.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Vetted - choosing an appropriate license</title>
    <link href="/2017/11/vetted-licensing/"/>
    <updated>2017-11-05T00:00:00+00:00</updated>
    <id>/2017/11/vetted-licensing/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;&lt;em&gt;See &lt;a href=&quot;/2017/11/vetted-a-new-hope/&quot;&gt;Vetted - a new project&lt;/a&gt; for some background.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’m hoping to start pushing some code soon. Before I do, it’s a good
opportunity to do some reading into a topic that I am more ignorant of than I
should be: software licensing. The following is what I’ve learnt so far.&lt;/p&gt;

&lt;p&gt;Disclaimer: I am not a lawyer and this may be totally incorrect, and as such
should not be used as the basis for any decision ever.&lt;/p&gt;

&lt;p&gt;Once code is released as open source software, most common
OSS licenses (GPL, BSD, MIT, Apache etc) do not allow for the revocation of
rights granted under the license. This is a good thing. Imagine having to be
prepared for any open source library/framework you’re currently using become
proprietary software with no warning. Such uncertainty would severely limit the
utility of open source software.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; possible for the current copyright owners to relicense their creations.
So, theoretically, any OSS software can be relicensed if all copyright owners
agree. The important part is that this relicensing does not revoke the rights
assigned under the previous license. So if I’ve released some software as open
source software, I can decide a year later to relicense it and create a
commercial version, with the following caveats:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I still own the copyright for the entire project
    &lt;ul&gt;
      &lt;li&gt;I need to have been the sole contributor to the project, or to have
ensured that contributors have assigned copyright to me for their work&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The existing rights assigned under the OSS license remain in place
    &lt;ul&gt;
      &lt;li&gt;If the license permits, anyone can fork the project at this point
and develop/use their own version&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given what I’ve learned above, I’m planning to license the project under an OSS
license, but I won’t accept any contributions until I’ve got some kind of
Contributor License Agreement (CLA) in place.&lt;/p&gt;

&lt;p&gt;This is likely the first of many posts where it might seem I’m researching a
topic and deliberating a little excessively, given I have no working software
or even a particularly interesting idea. It’s fairly premature to assume that
there are going to be any contributors to this project other than myself. I
don’t believe veterinary practice management software is so exciting that I am
going to be swamped with contributions. However, as I &lt;a href=&quot;/2017/11/vetted-a-new-hope/&quot;&gt;mentioned
earlier&lt;/a&gt;, this whole project is mainly a learning
opportunity for me.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Further resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://choosealicense.com&quot;&gt;choosealicense.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://haacked.com/archive/2006/01/24/TheDevelopersGuideToCopyrightLaw-Part1.aspx&quot;&gt;Phil Haack’s excellent three part series&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://opensource.com/article/17/9/open-source-licensing&quot;&gt;Open source licensing: What every technologist should know&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Vetted - a new project</title>
    <link href="/2017/11/vetted-a-new-hope/"/>
    <updated>2017-11-05T00:00:00+00:00</updated>
    <id>/2017/11/vetted-a-new-hope/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;When I was in high school, I created a fairly basic application for managing a
small veterinary practice. It’s written in Microsoft Access and is used by my
parents to manage their mobile veterinary business.&lt;/p&gt;

&lt;p&gt;I’m toying with rebuilding it as a web application. For its current users, the
main benefits of this would be:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;client contact details could be made available on a mobile device;&lt;/li&gt;
  &lt;li&gt;there will be no more (or at least fewer) issues with concurrent
modification (merging two access database files that have been modified
independently on different computers because Dropbox didn’t sync is no fun);
and&lt;/li&gt;
  &lt;li&gt;it will be accessible anywhere with internet access, so that my dad could do
accounts when he is away from home and has some downtime.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For me, it would mainly be a learning opportunity.&lt;/p&gt;

&lt;p&gt;Naming things is not my strong suit, so I’m going with ‘Vetted’ for now.&lt;/p&gt;

&lt;p&gt;I’m going to try to do the following throughout the project:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Apply domain driven design rigorously&lt;/li&gt;
  &lt;li&gt;Apply functional programming principles&lt;/li&gt;
  &lt;li&gt;Document failures and successes&lt;/li&gt;
  &lt;li&gt;Document my &lt;a href=&quot;#design-heuristics&quot;&gt;design heuristics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#develop-in-the-open&quot;&gt;Develop in the open&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Deploy continuously to &lt;del&gt;production&lt;/del&gt; &lt;em&gt;somewhere&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Focus on adding the most valuable parts first (e.g. make phone numbers
available online) &amp;amp; delivering vertical slices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m thinking that the basic architecture for now will be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Single page application&lt;/li&gt;
  &lt;li&gt;Elm frontend&lt;/li&gt;
  &lt;li&gt;Kotlin backend&lt;/li&gt;
  &lt;li&gt;Maybe some kind of event sourced data store, as I’d like to see how badly I
can shoot my foot off&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While I want to build something functional, I also want to learn about a few
techniques/patterns/tools that would be applicable on larger projects, so I might
be making some choices which seems strange. I’ll try to call these out as they
happen. I need to remember that &lt;a href=&quot;https://blog.bradfieldcs.com/you-are-not-google-84912cf44afb&quot;&gt;I am not Google&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m hoping to publish posts more regularly about this project, so keep an eye
out if you’re interested!&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;h3 id=&quot;design-heuristics&quot;&gt;Design Heuristics&lt;/h3&gt;

&lt;p&gt;I attended the excellent &lt;a href=&quot;http://exploreddd.com/&quot;&gt;Explore DDD conference&lt;/a&gt; this
year and one of my favourite talks was &lt;a href=&quot;https://www.youtube.com/watch?v=fWCt5KWfTuo&quot;&gt;Cultivating Your Design
Heuristics&lt;/a&gt; by Rebecca Wirfs-Brock.&lt;/p&gt;

&lt;p&gt;As defined in the talk, a heuristic is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;anything that provides a plausible aid (not a guaranteed aid) or direction in
defining a solution but is ultimately irrelevant to the final product&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rebecca encourages everyone to consciously document and cultivate heuristics,
learn others heuristics &amp;amp; discuss them and ultimately adapt (or wholesale
replace) your own heuristics when appropriate.&lt;/p&gt;

&lt;p&gt;It’s a great talk, and I’m going to try to document the heuristics that I find
myself using while working on this project.&lt;/p&gt;

&lt;h3 id=&quot;develop-in-the-open&quot;&gt;Develop in the open&lt;/h3&gt;

&lt;p&gt;I’m going to be writing about what I’m building, and the code will be available
on GitHub. However, I haven’t yet determined how to license the project. My
basic requirement is that I retain copyright and can relicense the project if
that’s ever required.&lt;/p&gt;

&lt;p&gt;Look out for a post on this in the near future.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Debugging slow bash startup files</title>
    <link href="/2017/10/debugging-slow-bash-startup-files/"/>
    <updated>2017-10-31T00:00:00+00:00</updated>
    <id>/2017/10/debugging-slow-bash-startup-files/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;Recently I found that opening a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt; session (e.g. when opening a new
terminal window) was getting a bit slow on my machine.  I take reasonable care
to make sure my dotfiles don’t get too crufty, and I keep them all in &lt;a href=&quot;https://github.com/mdjnewman/dotfiles&quot;&gt;version
control&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following is a walk through of how I went about debugging the issue.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So, how does one go about profiling what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt; is doing when starting a login
shell/interactive shell?&lt;/p&gt;

&lt;p&gt;My initial thought was to use some kind of system call tracing to see what
files were being opened/executed. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtrace&lt;/code&gt; exists on OS X, so let’s try that:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dtruss &lt;span class=&quot;nt&quot;&gt;-ef&lt;/span&gt; bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sadly, the output isn’t overly useful due to &lt;a href=&quot;https://unix.stackexchange.com/a/276219&quot;&gt;System Integrity
Protection&lt;/a&gt;. I don’t want to boot
into recovery mode, so what are our options?&lt;/p&gt;

&lt;p&gt;I regularly add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -o xtrace&lt;/code&gt; to my bash scripts … would the same thing
work for my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;? I added the line, and executed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+ source /Users/mnewman/.bash_profile
++ export PATH=/Users/mnewman/bin:/Users/mnewman/perl5/bin:/Users/mnewman/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/mnewman/.rvm/bin
++ PATH=/Users/mnewman/bin:/Users/mnewman/perl5/bin:/Users/mnewman/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/mnewman/.rvm/bin
++ for file in ~/.{path,bash_prompt,exports,aliases,functions,extra}
++ &apos;[&apos; -r /Users/mnewman/.path &apos;]&apos;
++ for file in ~/.{path,bash_prompt,exports,aliases,functions,extra}
++ &apos;[&apos; -r /Users/mnewman/.bash_prompt &apos;]&apos;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It looks like that works (the above is showing the start of my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_profile&lt;/code&gt;,
which is sourced from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;). There is a lot of output there though, and we
still don’t have any timing information. A little searching for variants of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash add timestamp to each line&lt;/code&gt; led me to &lt;a href=&quot;https://stackoverflow.com/a/9813614/415801&quot;&gt;an SO
answer&lt;/a&gt; recommending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts&lt;/code&gt;. Looking at the manual page for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ man ts

NAME
       ts - timestamp input

SYNOPSIS
       ts [-r] [-i | -s] [format]

DESCRIPTION
       ts adds a timestamp to the beginning of each line of input.

       The optional format parameter controls how the timestamp is formatted, as used by strftime(3). The default format is &quot;%b %d %H:%M:%S&quot;. In addition to the regular strftime
       conversion specifications, &quot;%.S&quot; and &quot;%.s&quot; are like &quot;%S&quot; and &quot;%s&quot;, but provide subsecond resolution (ie, &quot;30.00001&quot; and &quot;1301682593.00001&quot;).

       If the -r switch is passed, it instead converts existing timestamps in the input to relative times, such as &quot;15m5s ago&quot;. Many common timestamp formats are supported. Note that
       the Time::Duration and Date::Parse perl modules are required for this mode to work. Currently, converting localized dates is not supported.

       If both -r and a format is passed, the existing timestamps are converted to the specified format.

       If the -i or -s switch is passed, ts timestamps incrementally instead. In case of -i, every timestamp will be the time elapsed since the last timestamp. In case of -s, the time
       elapsed since start of the program is used.  The default format changes to &quot;%H:%M:%S&quot;, and &quot;%.S&quot; and &quot;%.s&quot; can be used as well.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So far so good, it looks like we could use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts -i&lt;/code&gt; and get the duration of
every command! I’d like to try this out, but how can we redirect the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xtrace&lt;/code&gt;
output to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Some further Googling led me to &lt;a href=&quot;https://unix.stackexchange.com/a/155553&quot;&gt;this SO
answer&lt;/a&gt;, which suggests using the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BASH_XTRACEFD&lt;/code&gt; variable to tell bash where to write its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xtrace&lt;/code&gt; output. After
some trial and error, I added a few lines to my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# open file descriptor 5 such that anything written to /dev/fd/5&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# is piped through ts and then to /tmp/timestamps&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;5&amp;gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;(&lt;/span&gt;ts &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%.s&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /tmp/timestamps&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BASH_XTRACEFD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;5&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Enable tracing&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Source my .bash_profile script, as usual&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PS1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bash_profile&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Upon restarting bash, this produces (a lot of) output in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/timestamps&lt;/code&gt;, and
each line contains an incremental timestamp, like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0.000046 ++ which brew
0.003437 +++ brew --prefix
0.025518 ++ &apos;[&apos; -f /usr/local/share/bash-completion/bash_completion &apos;]&apos;
0.000741 +++ brew --prefix
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These particular lines tell me that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew --prefix&lt;/code&gt; command executed and took
20ms.&lt;/p&gt;

&lt;p&gt;With output like the above, I had enough info to track down a couple of slow loading
scripts (like sourcing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvm.sh&lt;/code&gt;) and remove them from my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_profile&lt;/code&gt;.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Migrating a GitHub Pages blog with a custom domain to HTTPS</title>
    <link href="/2017/07/migrating-a-github-pages-blog-with-a-custom-domain-to-https/"/>
    <updated>2017-07-06T00:00:00+00:00</updated>
    <id>/2017/07/migrating-a-github-pages-blog-with-a-custom-domain-to-https/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;At the time of writing, this blog is hosted on &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt;,
which has been working well since I set it up a &lt;a href=&quot;https://github.com/mdjnewman/mdjnewman.github.io/commit/9e1e0836999aec7393d0314f9066040b94ef8c43&quot;&gt;few years back&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The only thing that has bugged me for a while now is that the whole site was
served over HTTP, rather than HTTPS.&lt;/p&gt;

&lt;p&gt;I wanted to move to move this blog to HTTPS, but with some constraints:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Continue using GitHub pages (it’s free and easy, I don’t want to manage a
server)&lt;/li&gt;
  &lt;li&gt;No certificate renewal (smart me plans for stupid me, who would surely forget
to renew a cert)&lt;/li&gt;
  &lt;li&gt;Continue using my domain (mdjnewman.me)&lt;/li&gt;
  &lt;li&gt;No cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub pages doesn’t support HTTPS for custom domain names, as it uses a
certificate with a wildcard SAN of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.github.io&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;CloudFlare&lt;/a&gt; offers HTTPS on a free plan, which
Troy Hunt has &lt;a href=&quot;https://www.troyhunt.com/how-to-get-your-ssl-for-free-on-shared/&quot;&gt;written
about&lt;/a&gt;
before.&lt;/p&gt;

&lt;p&gt;It looks like this will meet my constraints above - I get to keep using GitHub
Pages, I don’t have to manage a cert (CloudFlare takes care of this), and I can
keep using my custom domain.&lt;/p&gt;

&lt;p&gt;The steps I followed to do this were relatively simple:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Exported a zone file from current nameservers&lt;/li&gt;
  &lt;li&gt;Completed the CloudFlare onboarding, during which I imported the above zone file&lt;/li&gt;
  &lt;li&gt;Updated the authoritative DNS servers for my domain to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.ns.cloudflare.com&lt;/code&gt; name servers:
 &lt;img src=&quot;/public/images/2017/07/migrating-to-https-nameservers.png&quot; alt=&quot;Update name servers&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Tested the site out,
&lt;a href=&quot;https://github.com/mdjnewman/mdjnewman.github.io/commit/4b2a2237e1c00d9e280566f6d288f5870e250927&quot;&gt;fixed&lt;/a&gt;
a CSS link that was loaded over HTTP&lt;/li&gt;
  &lt;li&gt;Forced HTTPS in CloudFlare:
 &lt;img src=&quot;/public/images/2017/07/migrating-to-https-enforce-https.png&quot; alt=&quot;Enforcing HTTPS with CloudFlare&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;… and that was it. I finished this in part of an afternoon.&lt;/p&gt;

&lt;h2 id=&quot;shortcomings&quot;&gt;Shortcomings&lt;/h2&gt;

&lt;p&gt;There is one major shortcoming with this setup: &lt;strong&gt;there is no certificate
validation between CloudFlare and GitHub&lt;/strong&gt; (CloudFlare supports fetching from
an origin without validating certificates, which is the option I’ve chosen -
‘strict’ HTTPS can be enabled for most use cases).&lt;/p&gt;

&lt;p&gt;As we mentioned before, the GitHub cert is valid for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.github.io&lt;/code&gt;, and we’re
using my custom domain, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdjnewman.me&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we switched off the custom domain on GitHub, and did some smarts in
CloudFront to rewrite requests so that the request to GitHub was using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdjnewman.github.io&lt;/code&gt;, then we’d get HTTPS all the way to GitHub servers.&lt;/p&gt;

&lt;p&gt;CloudFlare does support
&lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/206652947-Using-Page-Rules-to-Re-Write-Host-Headers&quot;&gt;rewriting HTTP Host headers&lt;/a&gt;
, but it’s an enterprise feature.&lt;/p&gt;

&lt;p&gt;I could switch to using &lt;a href=&quot;https://aws.amazon.com/cloudfront/&quot;&gt;CloudFront&lt;/a&gt; with
an &lt;a href=&quot;https://aws.amazon.com/certificate-manager/&quot;&gt;AWS Certificate Manager&lt;/a&gt; cert,
which would meet all the above constraints except for ‘no cost’ (admittedly, my tiny
blog doesn’t get much traffic, so the cost would be minimal).&lt;/p&gt;

&lt;p&gt;Given that most of the shenanigans with injecting content into web sites
happens at the last leg of a connection (I’m looking at you, dodgy internet
cafe), I’m happy that the new setup for this blog mitigates that problem and am
willing to accept the cost/security trade-off. While it’s possible for someone
to perform a man in the middle attack and impersonate GitHub, given my site has
no sensitive information I’m not too worried about this threat model (Troy Hunt
also &lt;a href=&quot;https://www.troyhunt.com/cloudflare-ssl-and-unhealthy-security-absolutism/&quot;&gt;wrote
about&lt;/a&gt;
this trade-off).&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>When should I force push after rebasing?</title>
    <link href="/2017/07/when-should-i-force-push-after-rebasing/"/>
    <updated>2017-07-05T00:00:00+00:00</updated>
    <id>/2017/07/when-should-i-force-push-after-rebasing/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;tl;dr: assuming it’s your own branch, &lt;strong&gt;immediately&lt;/strong&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;On the last few projects I have been a part of, I have been the defacto Git
problem solver.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;https://imgs.xkcd.com/comics/git.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;https://imgs.xkcd.com/comics/git.png&quot; alt=&quot;XKCD Git Comic&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    (obligatory &lt;a href=&quot;https://xkcd.com/1597/&quot;&gt;xkcd&lt;/a&gt;)
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;On more than one occasion, I was presented with something like the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git l master
* 232e985 (origin/master, origin/HEAD, master) Feature 4
* 94989d0 Feature 3
* 296d0b3 Feature 2
* 4b856cd Feature 1

$ git l feature-5
* 5c31f6d (HEAD -&amp;gt; feature-5) Feature 4
* 420f83b Feature 3
* 724236a (origin/feature-5) Feature 5
* 296d0b3 Feature 2
* 4b856cd Feature 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the above, the commits adding features 3 and 4 on each branch are logically
the same, but on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feature-5&lt;/code&gt; branch they’ve somehow ended up after the
commit adding feature 5.&lt;/p&gt;

&lt;p&gt;The team was using feature branches, and the author of feature 5 above was
trying to rebase their changes onto master, but somehow ended up inserting
their commit between commits on master. At this stage, you’re in a pretty bad
place, as you’ve diverged from master.&lt;/p&gt;

&lt;p&gt;How did this happen? I’m guessing it was the following series of events:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Developer branches from master to create feature-5&lt;/li&gt;
  &lt;li&gt;Features 3 &amp;amp; 4 are pushed to master&lt;/li&gt;
  &lt;li&gt;Feature 5 is committed to the feature-5 branch&lt;/li&gt;
  &lt;li&gt;Developer runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase origin master&lt;/code&gt; or similar&lt;/li&gt;
  &lt;li&gt;… some time passes …&lt;/li&gt;
  &lt;li&gt;Developer runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase&lt;/code&gt; without really thinking about it&lt;/li&gt;
&lt;/ul&gt;

&lt;!--
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/gitgraph.js/1.11.3/gitgraph.js&quot;&gt;&lt;/script&gt;
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/gitgraph.js/1.11.3/gitgraph.css&quot; /&gt;

&lt;script&gt;
var gitGraphTemplateConfig = {
          colors: [&quot;#979797&quot;, &quot;#008fb5&quot;, &quot;#f1c109&quot;],
          branch: {
            lineWidth: 10,
            spacingX: 50,
            labelRotation: 0
          },
          commit: {
            spacingY: -80,
            dot: {
              size: 14
            },
            message: {
              displayAuthor: false,
              displayBranch: false,
              font: &quot;normal 14pt Arial&quot;
            }
          }
        };

var gitGraphTemplate = new GitGraph.Template( gitGraphTemplateConfig );
&lt;/script&gt;
--&gt;
&lt;p&gt;After the first few steps above, we have something like the following:&lt;/p&gt;

&lt;!--
&lt;div style=&quot;overflow-x: scroll&quot;&gt;
&lt;canvas id=&quot;gitgraph-1&quot; height=&quot;800&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script&gt;
var gitgraph = new GitGraph( { template: gitGraphTemplate, elementId: &quot;gitgraph-1&quot; })
var master = gitgraph.branch(&quot;master&quot;)
gitgraph.commit( { message: &quot;Feature 1&quot;, sha1: &quot;4b856cd&quot; })
gitgraph.commit( { message: &quot;Feature 2&quot;, sha1: &quot;296d0b3&quot; })
gitgraph.branch(&quot;feature-5&quot; )
gitgraph.commit( { message: &quot;Feature 5 (feature-5, origin/feature-5)&quot;, sha1: &quot;724236a&quot; })
master.checkout()
gitgraph.commit( { message: &quot;Feature 3&quot;, sha1: &quot;94989d0&quot; })
gitgraph.commit( { message: &quot;Feature 4 (master, origin/master)&quot;, sha1: &quot;232e985&quot; })
&lt;/script&gt;
--&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2017/07/git-1.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2017/07/git-1.png&quot; alt=&quot;Commits after creating feature branch&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;So far, so good. We want to rebase our changes onto master, so that we can test
and push our code. After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase origin master&lt;/code&gt;:&lt;/p&gt;

&lt;!--
&lt;div style=&quot;overflow-x: scroll&quot;&gt;
&lt;canvas id=&quot;gitgraph-2&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script&gt;
var gitgraph = new GitGraph( { template: gitGraphTemplate, elementId: &quot;gitgraph-2&quot; })
var master = gitgraph.branch(&quot;master&quot;)
gitgraph.commit( { message: &quot;Feature 1&quot;, sha1: &quot;4b856cd&quot; })
gitgraph.commit( { message: &quot;Feature 2&quot;, sha1: &quot;296d0b3&quot; })
gitgraph.branch(&quot;origin/feature-5&quot; )
gitgraph.commit( { message: &quot;Feature 5 (origin/feature-5)&quot;, sha1: &quot;724236a&quot; })
master.checkout()
gitgraph.commit( { message: &quot;Feature 3&quot;, sha1: &quot;94989d0&quot; })
gitgraph.commit( { message: &quot;Feature 4 (master, origin/master)&quot;, sha1: &quot;232e985&quot; })
gitgraph.commit( { message: &quot;Feature 5 (feature-5)&quot;, sha1: &quot;44e1c44&quot; })
&lt;/script&gt;
--&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2017/07/git-3.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2017/07/git-3.png&quot; alt=&quot;Commits after rebasing onto master&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;Still looking good. At this stage, we could &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push --force origin feature-5&lt;/code&gt;
and all would be well in the world.&lt;/p&gt;

&lt;p&gt;But what happens if we go for a tea and forget what we were doing (or we use an
overzealous git GUI tool), and we try to rebase onto &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin/feature-5&lt;/code&gt;?&lt;/p&gt;

&lt;!--
&lt;div style=&quot;overflow-x: scroll&quot;&gt;
&lt;canvas id=&quot;gitgraph-3&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script&gt;
var gitgraph = new GitGraph( { template: gitGraphTemplate, elementId: &quot;gitgraph-3&quot; })
var master = gitgraph.branch(&quot;master&quot;)
gitgraph.commit( { message: &quot;Feature 1&quot;, sha1: &quot;4b856cd&quot; })
gitgraph.commit( { message: &quot;Feature 2&quot;, sha1: &quot;296d0b3&quot; })
gitgraph.branch(&quot;feature-5&quot; )
gitgraph.commit( { message: &quot;Feature 5 (origin/feature-5)&quot;, sha1: &quot;724236a&quot; })
gitgraph.commit( { message: &quot;Feature 3&quot;, sha1: &quot;420f83b&quot; })
gitgraph.commit( { message: &quot;Feature 4 (feature-5)&quot;, sha1: &quot;5c31f6d&quot; })
master.checkout()
gitgraph.commit( { message: &quot;Feature 3&quot;, sha1: &quot;94989d0&quot; })
gitgraph.commit( { message: &quot;Feature 4 (master, origin/master)&quot;, sha1: &quot;232e985&quot; })
&lt;/script&gt;
--&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2017/07/git-2.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2017/07/git-2.png&quot; alt=&quot;Commits after rebasing from our remote branch - shows duplicate commits&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;What we see above is the result of Git rebasing commits &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;94989d0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;232e985&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;44e1c44&lt;/code&gt; on top of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin/feature-5&lt;/code&gt;. As the commit ID is computed by
hashing of the contents of a commit and its parent, the same logical commits
from master now exist on our branch with different IDs.&lt;/p&gt;

&lt;p&gt;This could have been avoided if we followed this rule of thumb:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;If you’re working on your own branch, always push immediately after rebasing.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some people on the team were seeing a message like the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Your branch and &apos;origin/feature-5&apos; have diverged,
and have 3 and 1 different commits each, respectively.
  (use &quot;git pull&quot; to merge the remote branch into yours)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and assuming that they should &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull --rebase&lt;/code&gt;, which in this case is exactly what you &lt;em&gt;don’t&lt;/em&gt; want.&lt;/p&gt;

&lt;p&gt;If you’re looking for further reading &lt;a href=&quot;https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F&quot;&gt;Getting Started - Git Basics&lt;/a&gt; covers the fundamentals and &lt;a href=&quot;http://learngitbranching.js.org/&quot;&gt;LearnGitBranching&lt;/a&gt; is a great interactive tool.&lt;/p&gt;

&lt;p&gt;Diagrams were created using &lt;a href=&quot;http://gitgraphjs.com/&quot;&gt;Gitgraph.js&lt;/a&gt;, and &lt;a href=&quot;/public/2017-07-05-when-should-i-force-push-after-rebasing-script.sh&quot;&gt;this script&lt;/a&gt; creates an example repository.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Monad transformers</title>
    <link href="/2016/07/monad-transformers/"/>
    <updated>2016-07-31T00:00:00+00:00</updated>
    <id>/2016/07/monad-transformers/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I’ve been spending some time working through &lt;a href=&quot;http://haskellbook.com/&quot;&gt;Haskell Programming From First
Principles&lt;/a&gt; recently which is a very comprehensive
introduction to functional programming and Haskell.&lt;/p&gt;

&lt;p&gt;One of the exercises to implement a simplified command line version of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Morra_(game)&quot;&gt;Morra&lt;/a&gt;, which involves keeping
track of scores and reading user input.&lt;/p&gt;

&lt;p&gt;My initial method to play a round looked something like this:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;playRound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;playRound&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;putStr&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P1: &quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;p1HandMaybe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHumanHand&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p1HandMaybe&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;-- error case 1&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;putStr&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P2: &quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;p2HandMaybe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHumanHand&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2HandMaybe&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;-- error case 2&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evenWins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateScores&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evenWins&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playRound&lt;/code&gt; takes the configuration for the game and the current score, and
returns a side effecting computation that will return a tuple with the new
scores and a boolean indicating if the game is finished.&lt;/p&gt;

&lt;p&gt;The method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getHumanHand&lt;/code&gt; used above returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IO (Maybe Int)&lt;/code&gt;, which can be
interpreted as a side effecting action that might return an integer (in this
case, the side effect is reading from the console and we can’t trust the user
to enter an integer, hence the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The problem then is that we’re then manually unpacking these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Maybe Int&lt;/code&gt;
values, which leads to the ugly nesting and case statements. However, we can
see on the lines marked ‘error case’ above that the handling for both cases is
the same - we assume that if the user has entered something other than an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;
that they want to end the game.&lt;/p&gt;

&lt;p&gt;I recently learned about Monad transformers, which allow you to compose monads.
In this case, we want to compose the Maybe monad with the IO monad, so we will
use &lt;a href=&quot;https://www.stackage.org/haddock/lts-6.2/transformers-0.4.2.0/Control-Monad-Trans-Maybe.html#g:1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MaybeT&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rewriting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getHumanHand&lt;/code&gt; to return a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MaybeT IO Int&lt;/code&gt; and rewriting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playRound&lt;/code&gt;
results in the following:&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;playRound&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;playRound&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;newScores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runMaybeT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;liftIO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;putStr&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P1: &quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p1Hand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHumanHand&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;liftIO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;putStr&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;P2: &quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;p2Hand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHumanHand&apos;&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evenWins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p1Hand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p2Hand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateScores&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evenWins&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newScores&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The nice thing about this implementation is that we’ve avoided the need for
pattern matching, as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;do&lt;/code&gt; block above where we’re dealing with the
potentially failing computations will immediately short circuit and return a
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Nothing&lt;/code&gt; if either user fails to provide a legitimate value.&lt;/p&gt;

&lt;p&gt;This is the first time I’ve actually used a Monad transformer, and it was good
to see how it cleans up the implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playRound&lt;/code&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>BFPG talk - Functional Programming in Scala Chapters 7 &amp; 8</title>
    <link href="/2016/06/talk_fp_in_scala_7_8/"/>
    <updated>2016-06-19T00:00:00+00:00</updated>
    <id>/2016/06/talk_fp_in_scala_7_8/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;In May, I presented a talk based on Chapters 7 &amp;amp; 8 of &lt;a href=&quot;https://www.manning.com/books/functional-programming-in-scala&quot;&gt;Functional Programming
in Scala&lt;/a&gt; at the
&lt;a href=&quot;http://www.meetup.com/Brisbane-Functional-Programming-Group/&quot;&gt;Brisbane Functional Programming
Group&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The talk explores the design and implementation of two functional libraries, one for
parallelism and one for property based testing.&lt;/p&gt;

&lt;p&gt;The video of the talk (also embedded below) is now available online at
&lt;a href=&quot;http://talks.bfpg.org/talks/2016-05-10.talk_fp_in_scala_7_8.html&quot;&gt;the BFGP talks site&lt;/a&gt;,
along with a link to the slides.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;http://talks.bfpg.org/past.html&quot;&gt;http://talks.bfpg.org/past.html&lt;/a&gt; for
other past BFPG presentations.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/ZSKeOZMoWUg&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
</content>
  </entry>
  
  <entry>
    <title>-Xlint:unchecked and -Werror for Java projects with Gradle</title>
    <link href="/2016/05/werror-java-gradle/"/>
    <updated>2016-05-04T00:00:00+00:00</updated>
    <id>/2016/05/werror-java-gradle/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I was recently working in a codebase where there were chunks of Java code that
used generic interfaces from the Apache Commons Collections project as well as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.util&lt;/code&gt; Collections in a type unsafe way, even though the
interfaces/classes that were being used supported generics.&lt;/p&gt;

&lt;p&gt;Our gradle build was emitting the following warning:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;:compileJavaNote: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This warning should be an error in my books. It’s possible to get this
behaviour by adding the following to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;tasks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JavaCompile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;compilerArgs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-Xlint:unchecked&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-Werror&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way, when our code is built everyone is aware when they’re using unsafe
operations, and can either fix the issue or supress the warning with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@SupressWarnings(&quot;unchecked&quot;)&lt;/code&gt; if it’s intentional.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Pedantic console for JavaScript tests</title>
    <link href="/2016/01/pedantic-console/"/>
    <updated>2016-01-30T00:00:00+00:00</updated>
    <id>/2016/01/pedantic-console/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;When running JavaScript tests that fire up a browser, it can be useful to
ensure that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.warn&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.error&lt;/code&gt; aren’t being called, and to have
your automated build fail if this starts happening.&lt;/p&gt;

&lt;p&gt;If you’re using a framework like Jasmine, you can place the following file in
your helpers directory to ensure that an exception will be thrown whenever a
call is made to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.warn&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console.error&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalConsole&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myError&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;originalConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;console.error called, failing test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;


&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;warn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;originalConsole&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myError&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;originalConsole&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;arguments&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;console.warn called, failing test&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I recently used this to locate all the places that &lt;a href=&quot;https://github.com/moment/moment/issues/1407&quot;&gt;a deprecated Moment.js
feature&lt;/a&gt; was being used in a
codebase.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Haskell stack, Yesod and Docker</title>
    <link href="/2016/01/haskell-stack-yesod-docker/"/>
    <updated>2016-01-01T00:00:00+00:00</updated>
    <id>/2016/01/haskell-stack-yesod-docker/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;h2 id=&quot;the-why&quot;&gt;The why&lt;/h2&gt;

&lt;p&gt;Over the break I’ve been working on a web app to replace a fairly old MS Access
Database that I built for my Dad to use in 2009 (he has a &lt;a href=&quot;https://www.facebook.com/Ross-Newman-Mobile-Vet-1461582037471594/&quot;&gt;mobile vet
business&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This seemed like a good chance to try out
&lt;a href=&quot;http://www.yesodweb.com/&quot;&gt;Yesod&lt;/a&gt;, a web framework for Haskell. The Yesod
philosophy is to leverage the Haskell type system wherever possible. For
example, in the Hamlet templating language everything from generating URLs to
including static files and generating forms is checked at compile time.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://haskellstack.org&quot;&gt;stack&lt;/a&gt; is a cross platform build tool for developing
Haskell programs which (when combined with
&lt;a href=&quot;https://www.stackage.org/&quot;&gt;Stackage&lt;/a&gt; makes Haskell development much more
enjoyable.&lt;/p&gt;

&lt;p&gt;I’d recommend stack for any new Haskell project, and hopefully this post can
point someone else in the right direction for a stack/Yesod/Docker project.&lt;/p&gt;

&lt;p&gt;I built a very basic site with Yesod and stack locally on OS X, based off the
yesod-postgres template (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack new mysite yesod-postgres&lt;/code&gt;). The yesod dev
server makes this all very easy, just running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack exec -- yesod devel&lt;/code&gt; will
keep Yesod running and recompiling the app whenever any changes are made.&lt;/p&gt;

&lt;p&gt;Soon it was time to make the app available somewhere in order to start
getting some feedback. At this stage, the most basic requirement for the
hosting was that it be low cost. Digital Ocean came to mind (use &lt;a href=&quot;https://www.digitalocean.com/?refcode=c55b676d3a2e&quot;&gt;this
link&lt;/a&gt; for $10 credit), and
I’m now using their one-click Docker droplet at USD $5 per month. This host can
run both the Yesod frontend and the PostgreSQL database.&lt;/p&gt;

&lt;p&gt;Binaries built locally on OS X won’t run on a Linux-based Digital Ocean droplet,
and it was a bit early to spend $$ on something like Snap or Travis, so I needed
a VM or container to run the build in.&lt;/p&gt;

&lt;h2 id=&quot;the-how&quot;&gt;The how&lt;/h2&gt;

&lt;h3 id=&quot;set-up&quot;&gt;Set up&lt;/h3&gt;

&lt;p&gt;stack has support for Docker to run the build and package the application, but
it isn’t currently supported when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boot2docker&lt;/code&gt; (see
&lt;a href=&quot;https://github.com/commercialhaskell/stack/issues/194&quot;&gt;these&lt;/a&gt;
&lt;a href=&quot;https://github.com/commercialhaskell/stack/issues/488&quot;&gt;issues&lt;/a&gt;), so I used a
simple Vagrantfile to start up a beefy VM:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;puppetlabs/centos-6.6-64-nocm&quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;virtualbox&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;4096&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;cpus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;modifyvm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--ioapic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;on&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Centos 6.6 might seem like an odd choice for a development environment, but the
Vagrant box was already on my laptop, so using it saved me the download time
(bandwidth is a precious commodity in semi-rural Australia).&lt;/p&gt;

&lt;p&gt;I didn’t bother setting up provisioning properly, but here are the commands
that are needed to get stack working:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Add FP Complete repo &amp;amp; install stack&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-sSL&lt;/span&gt; https://s3.amazonaws.com/download.fpcomplete.com/centos/6/fpco.repo | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/yum.repos.d/fpco.repo
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;stack

&lt;span class=&quot;c&quot;&gt;# Add EPEL repo and install Docker&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-iUvh&lt;/span&gt; http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker-io

&lt;span class=&quot;c&quot;&gt;# stack requires the Docker client to be able to connect&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# to the daemon without root, so add vagrant user to dockerroot group&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;gpasswd &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; dockerroot

&lt;span class=&quot;c&quot;&gt;# At this point, you&apos;ll need to log out and back in for&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the group change to take effect&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Setup iptables to allow Docker links to work&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; filter &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; DOCKER &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; 172.17.0.0/16 &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; docker0 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding the vagrant user to dockerroot comes with all the usual security issues,
but I’m not too worried about that here. There are some other suggestions in
the &lt;a href=&quot;http://docs.haskellstack.org/en/stable/docker_integration.html#docker&quot;&gt;stack documentation&lt;/a&gt;
for how to handle this.&lt;/p&gt;

&lt;h3 id=&quot;running-the-build&quot;&gt;Running the build&lt;/h3&gt;

&lt;p&gt;So, stack and Docker are now both installed. Enabling stack’s Docker
integration on the VM is as simple as modifying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.stack/config&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[vagrant@localhost ~]$ cat ~/.stack/config.yaml
docker:
  enable: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This gives the advantage of using Docker to run the builds on the VM, while not impacting
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yesod devel&lt;/code&gt; workflow on OS X.&lt;/p&gt;

&lt;p&gt;By default stack will use the fpco/stack-build repository to obtain an image to
run the build in. This suits me, as there is also fpco/stack-run for running the
binaries once they’re compiled. The build image includes everything that’s necessary
for building the whole of Stackage, whereas stack-run is more trimmed down.&lt;/p&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack build&lt;/code&gt; kicked off the build in the Docker container, which
completed successfully as all required dependencies (e.g. libpq and pg_config)
were already in the image. Thanks to &lt;a href=&quot;https://www.fpcomplete.com/&quot;&gt;FP Complete&lt;/a&gt;
for setting up these Docker containers for everyone to use!&lt;/p&gt;

&lt;h3 id=&quot;packaging-docker-image&quot;&gt;Packaging Docker image&lt;/h3&gt;

&lt;p&gt;stack’s support for creating container images is a relatively recent addition,
and currently isn’t covered well in the documentation. There is a reference to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image&lt;/code&gt; configuration section &lt;a href=&quot;http://docs.haskellstack.org/en/stable/yaml_configuration.html#image&quot;&gt;here&lt;/a&gt;,
which was enough for my needs. After added the relevant bits, my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack.yml&lt;/code&gt;
looks something like:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;lts-3.20&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&apos;&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;extra-deps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;mysite&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;library-only&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;extra-package-dbs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# This isn&apos;t required as it&apos;s set in the user config on the VM&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# docker:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#     enable: true&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mdjnewman/mysite&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;fpco/stack-run&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/app/config&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/app/static&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that in place, running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack image container&lt;/code&gt; produced a Docker container
ready to be pushed to Docker Hub:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[vagrant@localhost vagrant]$ stack image container
Sending build context to Docker daemon 34.25 MB
Sending build context to Docker daemon
Step 0 : FROM fpco/stack-run
 ---&amp;gt; db9b2a858ef5
Step 1 : ADD ./ /
 ---&amp;gt; e682c572d7ed
Removing intermediate container 1ce35ed1ccea
Successfully built e682c572d7ed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running a regular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker push&lt;/code&gt; published the image to the registry.&lt;/p&gt;

&lt;h3 id=&quot;deploying-to-digital-ocean&quot;&gt;Deploying to Digital Ocean&lt;/h3&gt;

&lt;p&gt;After all these steps, the final package was in Docker Hub and it was just a
matter of running the following commands on the droplet, and the site was live:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;postgres &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;uuidgen&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;POSTGRES_USER&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;postgres &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; postgres:9.3

&lt;span class=&quot;c&quot;&gt;# Yes, I know UUIDs don&apos;t make the best passwords :)&lt;/span&gt;

docker run              &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;                  &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /app             &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;--link&lt;/span&gt; postgres:postgres         &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 3000:3000        &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    mdjnewman/mysite    &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;PGHOST=$POSTGRES_PORT_5432_TCP_ADDR PGPASS=$POSTGRES_ENV_POSTGRES_PASSWORD /usr/local/bin/mysite&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The last command is running the Yesod server, with environment variables set to
the values provided by Docker (see
&lt;a href=&quot;https://github.com/yesodweb/yesod/wiki/Configuration#overriding-configuration-values-with-environment-variables&quot;&gt;here&lt;/a&gt; for info about setting configuration variables in Yesod).&lt;/p&gt;

&lt;h2 id=&quot;the-results&quot;&gt;The results&lt;/h2&gt;

&lt;p&gt;I’m very happy with the Yesod workflow, and stack’s Docker integration makes
deploying a lot easier as I don’t have to worry about what packages are in my
build and test environments. Seems like a good compromise between manually
copying files around and having a full CD pipeline.&lt;/p&gt;

&lt;p&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stack build&lt;/code&gt; with a LTS resolver and an isolated container is also the
holy grail of repeatable builds!&lt;/p&gt;

&lt;p&gt;There is still a lot that would need to be done (improving security, backups,
logging etc) before this was closer to a production environment, but it’s good
enough as a development region.&lt;/p&gt;

&lt;p&gt;This whole process (including writing this post) from having something that I
wanted to deploy to being able to view the live site took less than a day,
and I was learning a lot along the way. Deciding where was the best place to
host the site and waiting for Docker to pull the fpco/stack-build image took up
most of the time!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Simon Peyton Jones on maintenance with strong types</title>
    <link href="/2014/06/simon-peyton-jones-on-maintenance-with-strong-types/"/>
    <updated>2014-06-26T00:00:00+00:00</updated>
    <id>/2014/06/simon-peyton-jones-on-maintenance-with-strong-types/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;People don’t like fixing type errors, but they are a lot easier to fix than runtime errors… The single biggest thing going for static typing is not so much that it helps you write your program in the first place, but it helps you maintain your program.&lt;/p&gt;

  &lt;p&gt;GHC itself is an example – it’s now 150,000 lines of Haskell &amp;amp; twenty years old and I regularly refactor it in pretty large scale ways. I just wouldn’t dare do that if I didn’t have static typing to keep me sane. It’s this enormous code base, chunks of which I’ve forgotten about, and yet I can confidently make systemic changes to it because I know the type checker is going to catch all the places that change needs to go.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simon Peyton Jones, speaking on &lt;a href=&quot;http://www.functionalgeekery.com/episode-11-simon-peyton-jones/&quot; title=&quot;Functional Geekery Episode 11 – Simon Peyton Jones&quot;&gt;Functional Geekery Episode 11&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The part about GHC is anecdotal evidence, to be sure, but it makes the point nicely.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Why Functional Programming Matters</title>
    <link href="/2014/06/why-functional-programming-matters/"/>
    <updated>2014-06-13T00:00:00+00:00</updated>
    <id>/2014/06/why-functional-programming-matters/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;The following is the conclusion from a paper entitled ‘Why Functional Programming Matters’:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In this paper, we’ve argued that modularity is the key to successful programming. Languages that aim to improve productivity must support modular programming well. But new scope rules and mechanisms for separate compilation are not enough — modularity means more than modules. Our ability to decompose a problem into parts depends directly on our ability to glue solutions together. To support modular programming, a language must provide good glue. Functional programming languages provide two new kinds of glue — higher-order functions and lazy evaluation. Using these glues one can modularize programs in new and useful ways, and we’ve shown several examples of this. Smaller and more general modules can be reused more widely, easing subsequent programming. This explains why functional programs are so much smaller and easier to write than conventional ones. It also provides a target for functional programmers to aim at. If any part of a program is messy or complicated, the programmer should attempt to modularize it and to generalize the parts. He or she should expect to use higher-order functions and lazy evaluation as the tools for doing this.&lt;/p&gt;

  &lt;p&gt;Of course, we are not the first to point out the power and elegance of higher-order functions and lazy evaluation. For example, Turner shows how both can be used to great advantage in a program for generating chemical structures. Abelson and Sussman stress that streams (lazy lists) are a powerful tool for structuring programs. Henderson has used streams to structure functional operating systems. But perhaps we place more stress on functional programs’ modularity than previous authors.&lt;/p&gt;

  &lt;p&gt;This paper is also relevant to the present controversy over lazy evaluation. Some believe that functional languages should be lazy; others believe they should not. Some compromise and provide only lazy lists, with a special syntax for constructing them (as, for example, in Scheme). This paper provides further evidence that lazy evaluation is too important to be relegated to second-class citizenship. It is perhaps the most powerful glue functional programmers possess. One should not obstruct access to such a vital tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;http://comjnl.oxfordjournals.org/content/32/2/98.short&quot; title=&quot;Why Functional Programming Matters&quot;&gt;J. Hughes, “Why Functional Programming Matters,” Comput. J., vol. 32, pp. 98–107, 1989.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This paper was written twenty years ago – the more things change, the more they stay the same. I’d urge any programmer (whether currently interested in FP or otherwise) to read this paper if you haven’t already.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>ThoughtWorks LevelUp EXP Brisbane – Take 2</title>
    <link href="/2014/05/thoughtworks-levelup-exp-brisbane-take-2/"/>
    <updated>2014-05-05T00:00:00+00:00</updated>
    <id>/2014/05/thoughtworks-levelup-exp-brisbane-take-2/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">
&lt;figure&gt;
    &lt;a href=&quot;/public/images/2014/05/ThoughtWorks-LevelUp-EXP-Brisbane-May-2014.jpg&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2014/05/ThoughtWorks-LevelUp-EXP-Brisbane-May-2014.jpg&quot; alt=&quot;&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    LevelUp EXP Brisbane Attendees (thanks Alexandra Tran for the photo!)
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;ThoughtWorks ran another great express &lt;a href=&quot;https://www.thoughtworks.com/en-au/about-us/events/level-up&quot; title=&quot;LevelUp&quot;&gt;LevelUp&lt;/a&gt; event on Saturday at their Brisbane office. LevelUp events aim to help students bridge the gap between university and their first full-time job. LevelUp EXP is a mini-conference with a number of talks and hands on sessions, as well as lots of opportunities to mingle with the ThoughtWorks employees and other attendees. One theme that recurred through almost every talk of the day was focussing on the user at every stage of the development process – if you’re not building something that your users can use, then you’re wasting time. This does mean &lt;strong&gt;users&lt;/strong&gt;, not customers. You can be building a product for a client, but it’s ultimately the user’s experience that will determine success.&lt;/p&gt;

&lt;h2 id=&quot;real-project-example-dominos-html5-in-brisbane&quot;&gt;Real Project Example: Domino’s HTML5 in Brisbane&lt;/h2&gt;

&lt;p&gt;First up was Mark Ryall (&lt;a href=&quot;https://twitter.com/markryall&quot; title=&quot;Mark Ryall (markryall) on Twitter&quot;&gt;@markryall&lt;/a&gt;) discussing the recent consolidation of three separate websites into a single HTML5 site for the Dominos pizza franchise in Australia, New Zealand and the Netherlands. The new site was to replace separate Flash, mobile and accessibility-focussed sites, and was a greenfield project. From a software process perspective, the project kicked off with a two-week inception where BAs, developers, designers and testers worked together for two weeks to get initial requirements worked out. Mark pointed out that this is an effective alternative to the business struggling to work out requirements on their own for six months before getting anyone else involved. It reminded me of the quote that’s often attributed to Henry Ford:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If I’d asked people what they wanted, they would have said a faster horse.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The point is that the business doesn’t always know what they want, and even if they do, they may not be able to articulate that in such a way that both parties have the same vision. The rest of the project ran in two-week iterations, with showcases at the end of every iteration. Mark mentioned that the biggest challenges (from a technical perspective) in this project were internationalisation (I18N) and localisation. As Mark explained it, internationalisation ensures everything is available in the correct languages for the correct region, whereas localisation focusses on differences such as different address formats (another example of what this site in particular has to handle is that Domino’s in NL doesn’t provide catering, like it does in AU). There was a heavy emphasis on test automation in this project, and &lt;a href=&quot;http://docs.seleniumhq.org/projects/webdriver/&quot; title=&quot;Selenium WebDriver&quot;&gt;Selenium WebDriver&lt;/a&gt; was used for automated browser testing. WebDriver allows single tests to be written to target more than one browser, and are more robust than trying to guess what the browser is doing and interspersing your tests with loads of sleep() calls. In order to make tests more readable for everyone on the project (BAs/the business included), &lt;a href=&quot;http://www.specflow.org/&quot; title=&quot;Specflow - Cucumber for .NET&quot;&gt;Specflow&lt;/a&gt; was used. Specflow is a .NET alternative to Cucumber, and uses a similar declarative style to define specifications &amp;amp; expected behaviour. Tests are then generated from these easy to read specifications, targeting whichever testing framework you’re using (NUnit in this case). Given this site was replacing an existing site with a focus on accessibility, Domino’s required this site to be just as accessible for people using screen readers and keyboard only navigation. Accessibility is something that is easy to overlook, but every developer should make the effort to do these things correctly (using alternative text, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA&quot; title=&quot;ARIA - Accessibility | MDN&quot;&gt;ARIA tags&lt;/a&gt;, skip links for navigation etc). If you want to know more about how important accessibility is, Scott Hanselman recently did an &lt;a href=&quot;http://www.hanselminutes.com/413/im-a-blind-software-technician-ask-me-anything-with-katherine-moss&quot; title=&quot;I&apos;m a Blind Software Technician - Ask Me Anything! with Katherine Moss&quot;&gt;interesting interview with Katherine Moss&lt;/a&gt;, a blind software technician.&lt;/p&gt;

&lt;h2 id=&quot;the-lego-game&quot;&gt;The Lego Game&lt;/h2&gt;

&lt;p&gt;The Lego Game is a game designed to give you a taste of the Agile software development process.  Our task was building a Lego ‘animal’ with a client in mini sprints lasting a few minutes each. We worked through everything from estimation to a retrospective in less than ten minutes, and completed three iterations with a client who wasn’t afraid to change their mind. An interesting resource that was mentioned by the ThoughtWorks employees running the Lego game was the Retrospective Prime Directive by Norman Keith:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I thought this was a good guideline for running retrospectives, as it ensures that you focus on what went well and what can be improved, and not on trying to assign blame. There are &lt;a href=&quot;https://www.google.com.au/search?q=agile+lego+game&quot; title=&quot;agile lego game - Google&quot;&gt;plenty of pages&lt;/a&gt; describing the agile Lego game on the net if you want to read more.&lt;/p&gt;

&lt;h2 id=&quot;agile-101-with-a-business-analyst&quot;&gt;Agile 101 with a Business Analyst&lt;/h2&gt;

&lt;p&gt;Agile 101 with a BA by &lt;a href=&quot;https://henrylawson.net/&quot; title=&quot;Henry Lawson: Home&quot;&gt;Henry Lawson&lt;/a&gt; was the first of the twenty-minute lightning talks for the day. In twenty minutes, Henry managed to cover a brief history of Agile, the Agile manifesto and different Agile methodologies. There was more about Agile on the cards but the twenty-minute timeline had to be adhered to! The following paragraphs sum up the main points of the talk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agile manifesto&lt;/strong&gt;: the &lt;a href=&quot;http://agilemanifesto.org/&quot; title=&quot;Manifesto for Agile Software Development&quot;&gt;Agile manifesto&lt;/a&gt; is what gave the movement towards iterative, lightweight processes a name. Written in 2001 by several prominent figures in the software industry, the core of the Agile manifesto is the following four points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Individuals and interactions over processes and tools&lt;/li&gt;
  &lt;li&gt;Working software over comprehensive documentation&lt;/li&gt;
  &lt;li&gt;Customer collaboration over contract negotiation&lt;/li&gt;
  &lt;li&gt;Responding to change over following a plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The differences between traditional Waterfall methodologies and Agile&lt;/strong&gt;: The waterfall model is a sequential design process, where each stage is completed and locked-down before the next is started.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2014/05/waterfall-model.png&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2014/05/waterfall-model.png&quot; alt=&quot;Waterfall model of system development&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    Waterfall model of system development – avoid it! (you want the cycle above to take two weeks, not twelve months) (&lt;a href=&quot;http://en.wikipedia.org/wiki/File:Waterfall_model.svg&quot; title=&quot;File:Waterfall model.svg&quot;&gt;source&lt;/a&gt;)
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;While waterfall might work for other engineering projects (like building a bridge), it’s not really suitable for software development (too many software projects have elements of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Wicked_problem&quot; title=&quot;Wicked problem - Wikipedia&quot;&gt;wicked problem&lt;/a&gt;). I won’t go into the benefits of Agile or Agile processes in too much detail here, as there is plenty more information available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different agile methodologies&lt;/strong&gt;: Examples of agile methodologies include Scrum, Kanban, Lean, XP and Crystal Clear. The main difference between these methodologies is the practices, such as daily Scrum meetings or pair programming in XP. The general processes are similar, and there is no reason you can’t mix and match.&lt;/p&gt;

&lt;h2 id=&quot;functional-programming&quot;&gt;Functional Programming&lt;/h2&gt;

&lt;p&gt;Hugo Firth (&lt;a href=&quot;https://twitter.com/hugo_firth&quot; title=&quot;Hugo (hugo_firth) on Twitter&quot;&gt;@hugo_firth&lt;/a&gt;) was giving the next lightning talk, this time with a quick intro to functional programming concepts. There are a number of programming paradigms, such as procedural and object-oriented (OO). Procedural code (e.g. C/BASIC code) doesn’t provide many ways to create abstractions and manage state. OO, such as you’ve probably encountered in Java/C#/C++ allows abstractions to hide global state. Functional programming on the other hand is all about removing state where possible, and programming with pure functions. Hugo went through some common functions you’ll meet in functional programming, such as map &amp;amp; filter by providing some simple examples in Clojure. If you want to see a less rushed presentation by Hugo, his recent talk at the Brisbane Functional Programming Group is available on Vimeo.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;&lt;iframe src=&quot;https://player.vimeo.com/video/80576311&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://www.meetup.com/Brisbane-Functional-Programming-Group/&quot; title=&quot;Brisbane Functional Programming Group (BFPG) (Brisbane)&quot;&gt;BFPG&lt;/a&gt; is a great community if you’re looking to learn more about functional programming – I’ve always found everyone there to be extremely willing to help.&lt;/p&gt;

&lt;h2 id=&quot;working-in-different-environments-from-heaven-to-hell&quot;&gt;Working in different environments… from Heaven to Hell&lt;/h2&gt;

&lt;p&gt;The last lightning talk in the first session was by Claudia Ferreira (&lt;a href=&quot;https://twitter.com/claudia_onfire&quot; title=&quot;claudia ferreira (claudia_onfire) on Twitter&quot;&gt;@claudia_onfire&lt;/a&gt;), providing some practical advice for dealing with difficult work environments. You shouldn’t assume that the end of uni is the end of the hard work. Starting a new job, meeting new people and adapting to company culture is just as hard. Also, you don’t want to fall into the trap of thinking that you know everything and that you can stop learning. There is an almost endless variety of work environments, some good and some not so great. Claudia showed the following clip from The Matrix and told us about a time she was in this exact position.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/c_Ot1OEfk9I&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;

&lt;p&gt;Claudia’s boss basically said you’re here to work, not think, and there are hundreds of people who can fill this spot if you aren’t happy with that. Hopefully you won’t find yourself in a situation this extreme, but chances are you’ll have a boss you’re not overly excited about working with at some point in your career. If you find yourself in this situation, don’t just bottle it up and say nothing. Your team is there to help, you should be able to trust them and speak to them about issues. It’s important to have a good relationship with your team, as they’re the people that you spend the majority of your day with. So don’t stress if you’re confronted with a difficult situation, just take a deep breath, speak up if you really don’t agree and be the bigger person.&lt;/p&gt;

&lt;h2 id=&quot;the-way-of-the-consultant&quot;&gt;The Way of the Consultant&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://vizualize.me/panda#.U2bXgfmSzOM&quot; title=&quot;vizualize.me - Sarbashrestha Panda&quot;&gt;Sarbashrestha Panda&lt;/a&gt; has been a consultant for 5-6 years, working as an analyst and project manager on many projects. There are many types of consulting, from technical to business strategy. Technical consulting still has a strong focus on the business needs, no matter what area you’re in you are helping solve a problem the business is having. As Panda explained it, the role of the consultant is to always ask the difficult questions and have the difficult conversations. You want to make a problem visible, make people think and help to implement solutions. As a consultant, your knowledge should drive change.&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2014/05/rhino-painting.jpg&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2014/05/rhino-painting.jpg&quot; alt=&quot;Rhinoceros painting&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    Most problems are people problems - recognise that everyone has a different perspective (&lt;a href=&quot;http://alligator-sunglasses.com/post/8929519267/poor-rhinoceros&quot; title=&quot;Poor rhinoceros&quot;&gt;source&lt;/a&gt;)
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;p&gt;If you’re working as a consultant, embrace the opportunity to work on many different projects – you can’t develop a broad skill set without experience. You can be a consultant in any language with any technology, and after a few years should develop the skills to become a consultant for a specific domain. Don’t let yourself get cornered into a specific technology – technologies change far too fast.&lt;/p&gt;

&lt;h2 id=&quot;ui-dev-what-and-why&quot;&gt;UI Dev. What and Why?&lt;/h2&gt;

&lt;p&gt;Eru Penkman gave the next talk, which was originally entitled ‘UI Dev. What and Why?’, but seemed to have transformed into a talk about programmer culture and day-to-day life. Eru pointed out a bunch of things that a lot of programmers/developers have in common. Most of the people in the room had read XKCD at some point, everyone had used Stack Overflow, lots of people read similar blogs etc. Having all these elements in common helps when working in a team, which as Eru pointed out is pretty much what development is about. It’s very rare to have a project where you don’t interact with a number of people throughout the day. There are plenty of resources for developers, as everyone uses Stack Overflow it means that SO can answer almost any question, and lots of problems you might want to solve have already been solved by one open source project or another. However, don’t just consume these resources – make accounts on SO/GitHub and start contributing!&lt;/p&gt;

&lt;h2 id=&quot;what-they-didnt-tell-you-about-testing&quot;&gt;What they didn’t tell you about Testing!&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do not assume anything. Ever.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final lightning talk for the day was by Leonor Salazar &amp;amp; Brian Mason, covering testing and quality. The first point that Leo &amp;amp; Brian drilled home is that quality is subjective. Everyone has different ideas of quality, and you can’t do much meaningful testing without knowing what quality means for your project. Quality as defined by the users of the product is the most important. Everyone on a project should be thinking about quality, it’s not something that one person can ‘add in’ at the end. There is also a simple and compelling economic argument for having quality on everyone’s mind: it’s up to 1000x times more expensive to fix a bug in production than it is in analysis. Don’t let that cripple you or force you into a big-design-up-front type approach, but keep quality at the front of your mind.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Development is solving problems, testing is asking questions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You need to ask yourself four questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Are we doing the right things?&lt;/li&gt;
  &lt;li&gt;Are we doing the things right?&lt;/li&gt;
  &lt;li&gt;Are we getting them done well?&lt;/li&gt;
  &lt;li&gt;Are we getting the benefits?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no point obsessing over whether you’re doing things right if you’re not doing the right things! Testers also have the opportunity to improve process, and take the product in new directions.&lt;/p&gt;

&lt;h2 id=&quot;user-testing-what-you-build--hands-on-session&quot;&gt;User Testing what you Build – Hands On Session&lt;/h2&gt;

&lt;p&gt;Carrying on with the theme of user first was Pete Chemsripong, with a hands on session where each team had to develop a ‘product’ that was then tested by a user. For example, a media remote control for a user with boxing gloves on or a lift control panel for someone carrying 15 bags of groceries. To design a good user experience, you need to ask why you’re building anything in the first place. You need to understand why people would use this product. Ultimately the answer to a question like ‘What makes Google better than Bing?’ is always that it offers a better user experience and satisfies the users needs. It doesn’t matter what you build or how you build it if people don’t enjoy using it. User testing also doesn’t have to be expensive. You can even grab a dev from another team who hasn’t touched your project. Chances are they’re going to find a lot of the same issues as a ‘real’ user of the software, allowing you to pick the low hanging fruit for minimal cost. Pete showed a video from a recent ThoughtWorks experiment, where an &lt;a href=&quot;http://www.thoughtworks.com/clients/woolworths&quot; title=&quot;Woolworths | ThoughtWorks&quot;&gt;in-store innovation lab at a Woolworths&lt;/a&gt; store produced loads of great feedback in a very short time. The other ThoughtWorkers present mentioned &lt;a href=&quot;http://www.joelonsoftware.com/articles/UsabilityTestingwithMorae.html&quot; title=&quot;Usability Testing with Morae by Joel Spolsky&quot;&gt;Usability Testing with Morae&lt;/a&gt; as a good read for more information about inexpensive usability testing.&lt;/p&gt;

&lt;h2 id=&quot;tdd--from-woe-to-go-in-10-minutes--hands-on-session&quot;&gt;TDD – from woe to go in 10 minutes – Hands On Session&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;As professional developers, the burden of proving a system works lies with us.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Steve Morris held the floor for the final session of the day, and did a great job showing everyone how simple test driven development can be. TDD provides the following benefits:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Shows the code does what you say it does&lt;/li&gt;
  &lt;li&gt;Improves quality by making code more testable&lt;/li&gt;
  &lt;li&gt;Allows you to figure out what to test only once – no more writing a monolithic class/function and then spending time working through what needs to be tested over and over&lt;/li&gt;
  &lt;li&gt;At any time, you can see what is broken and whether your code is shippable (as there is never code that isn’t covered by tests)&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;TDD is coding with intent – don’t code by accident.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The ‘test’ in TDD could just as easily be replaced by ‘expectation’, ‘behaviour’, ‘specification’ or ‘intent’. It’s as much about helping to define expected behaviour and a minimal specification as it is about testing actual code. It doesn’t matter if you’re a developer or not, TDD provides the same benefits to BAs, managers and QA testers. I couldn’t write this post without including the TDD mantra, lest Steve think we all learnt nothing at all from the talk. The TDD mantra is as follows&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Red – write a minimal failing test&lt;/li&gt;
  &lt;li&gt;Green – write the minimum amount of code to make the test pass&lt;/li&gt;
  &lt;li&gt;Refactor – incrementally refactor the code (both code under test &lt;strong&gt;and&lt;/strong&gt; the tests themselves – test code is first class code!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing tests before code forces you to think about naming, architecture, APIs and design without considering implementation details. This helps with design and forces us to progress with intent, to avoid building unnecessary features. The refactor step encourages design improvements in incremental steps, rather than writing a bunch of code and then struggling through a ‘big bang’ refactor later in the project. Failing tests are not a failure of any kind, rather, they are statements of intent. The minimal failing test doesn’t even have to compile. A test that doesn’t compile signifies an intent to write the code to make it compile. In this way tests are documentation of future intent as well as progress to date. The hands on component of this talk included getting testing environments for C# and Node.js set up and writing our first code using TDD. Set-up for C# is as simple as installation of a testing framework like NUnit, which in a newer version of Visual Studio is as easy as running&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Install-Package Nunit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;in the package manager console. The set up for Node.js was just as simple, with npm installed simply run&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npm install karma
npm install phantomjs
npm install jasmine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;from your favourite shell. In the talk, it was possible to get this environment set up and have our first test running in under ten minutes for each environment. There really isn’t any excuse for not giving TDD a try! Steve also pointed out that TDD (like most concepts in software development) &lt;a href=&quot;http://arialdomartini.wordpress.com/2012/07/20/you-wont-believe-how-old-tdd-is/&quot; title=&quot;You won’t believe how old TDD is&quot;&gt;isn’t as new as you might think&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The second LevelUp EXP event in Brisbane was eye-opening, and I think the attendees learnt a lot to complement what is taught at university. If you attended/presented and I’ve omitted anything, please let me know and I’ll fix it up. My post about the first Brisbane LevelUp event is &lt;a href=&quot;/2013/10/levelup-exp-brisbane/&quot; title=&quot;ThoughtWorks LevelUp EXP Brisbane&quot;&gt;here&lt;/a&gt;, and more about ThoughtWorks LevelUp can be found on Twitter (&lt;a href=&quot;https://twitter.com/TW_LevelUp&quot;&gt;@TW_LevelUp&lt;/a&gt;) and &lt;a href=&quot;https://www.facebook.com/ThoughtworksLevelUp&quot;&gt;Facebook&lt;/a&gt;.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Working on Haskell code in vim</title>
    <link href="/2014/04/working-on-haskell-code-in-vim/"/>
    <updated>2014-04-17T00:00:00+00:00</updated>
    <id>/2014/04/working-on-haskell-code-in-vim/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I decided to get a fresh vim install properly set up for some Haskell development, and went down the road of using &lt;a href=&quot;https://github.com/bitc/hdevtools&quot; title=&quot;hdevtools on GitHub&quot;&gt;hdevtools&lt;/a&gt;, &lt;a href=&quot;https://github.com/bitc/vim-hdevtools&quot; title=&quot;vim-hdevtools on GitHub&quot;&gt;vim-hdevtools&lt;/a&gt; and &lt;a href=&quot;https://github.com/scrooloose/syntastic&quot; title=&quot;syntastic on GitHub&quot;&gt;Syntastic&lt;/a&gt;. Below are notes on some issues I encountered setting up vim-hdevtools.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The instructions on the GitHub page for hdevtools &amp;amp; vim-hdevtools linked above are simple enough, but I ran into a couple of issues. I’m using the sandbox feature added in Cabal 1.18, and by default hdevtools doesn’t know to look for a .cabal-sandbox folder. So, when I tried to use any of the hdevtools commands, I received an error message similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error loading targets
(file):
Could not find module `(module)&apos;
Use -v to see a list of the files searched for.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is an issue that a few people have run into, and I found a link to &lt;a href=&quot;http://lpaste.net/94999&quot; title=&quot;vim config for hdevtools and cabal sandboxes&quot;&gt;this solution&lt;/a&gt; in the archives of the &lt;a href=&quot;http://www.haskell.org/haskellwiki/IRC_channel&quot; title=&quot;View source for IRC channel - HaskellWiki&quot;&gt;#Haskell&lt;/a&gt; IRC channel.
Adding it to my .vimrc seems to have fixed this error, and I can now use all the hdevtool commands in vim. I’m still having issues with 
*.cabal files that specify default-extensions (vim-hdevtools doesn’t seem to pick these up).&lt;/p&gt;

&lt;p&gt;Also, if you get an error message similar to the following:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E492: Not an editor command: ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;make sure that hdevtools is on your path and that you have plugin files for specific file types enabled by adding&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;filetype plugin on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to your .vimrc.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Installing self signed certificates on Android (Jelly Bean)</title>
    <link href="/2013/11/jelly-bean-self-signed-certificates/"/>
    <updated>2013-11-06T00:00:00+00:00</updated>
    <id>/2013/11/jelly-bean-self-signed-certificates/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I was pretty happy when I found out Android now supports installing self signed certificates, but had some trouble getting the certificate I use for administering this blog installed.&lt;/p&gt;

&lt;p&gt;So, a quick note for anyone who is attempting to install a self signed SSL certificate on Jelly Bean Android devices: &lt;strong&gt;you can only install a root CA certificate&lt;/strong&gt; (i.e. a certificate with “Subject Type=CA”).&lt;/p&gt;

&lt;p&gt;Trying to install a certificate for a single site (i.e. a certificate with “Subject Type=End Entity”) isn’t possible as far as I can tell. I don’t have any references for this, it’s just based from my experience, so let me know if you’ve experienced otherwise.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Two-factor authentication and ‘trusted’ devices</title>
    <link href="/2013/10/two-factor-authentication-and-trusted-devices/"/>
    <updated>2013-10-30T00:00:00+00:00</updated>
    <id>/2013/10/two-factor-authentication-and-trusted-devices/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20191028203113/https://pando.com/2013/10/26/i-challenged-hackers-to-investigate-me-and-what-they-found-out-is-chilling/&quot; title=&quot;I challenged hackers to investigate me and what they found out is chilling - PandoDaily&quot;&gt;“I challenged hackers to investigate me and what they found out is chilling”&lt;/a&gt; is an interesting article – it’s the story of a couple who challenged a hacking team to pen-test their digital lives. To give some context to the following quote, their laptop has been compromised and user ID and password for their on-line banking account at Chase has been stolen by the ethical hacking team:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Chase.com uses a two-step verification system, which momentarily stymied SpiderLabs’ hackers. Every time she or I logs on from an IP address that Chase doesn’t recognize, it offers to send us an activation code via text to our mobile phones. But a search of Charlotte’s hard drive revealed Chase cookies, which the team copied and used to convince Chase that she was logging in from home.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could argue that if your PC has been this thoroughly compromised then you have bigger problems, but it still points out how limited some two-factor authentication systems can be if you allow devices to be remembered/trusted.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>ThoughtWorks LevelUp EXP Brisbane</title>
    <link href="/2013/10/levelup-exp-brisbane/"/>
    <updated>2013-10-29T00:00:00+00:00</updated>
    <id>/2013/10/levelup-exp-brisbane/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;On Saturday I was lucky enough to attend &lt;a href=&quot;http://levelup.thoughtworks.com/brisbane/&quot; title=&quot;ThoughtWorks LevelUp EXP Brisbane&quot;&gt;ThoughtWorks LevelUp EXP&lt;/a&gt; at the ThoughtWorks Brisbane office.&lt;/p&gt;

&lt;p&gt;As well as plenty of opportunities to chat with the ThoughtWorkers (and Chad!) who kindly gave up their Saturday, there were six presentations throughout the day:&lt;/p&gt;

&lt;h2 id=&quot;opening-keynote-design-thinking&quot;&gt;Opening Keynote: Design Thinking&lt;/h2&gt;

&lt;p&gt;Ben Melbourne (&lt;a href=&quot;https://twitter.com/benmelb&quot; title=&quot;Ben Melbourne (benmelb) on Twitter&quot;&gt;@benmelb&lt;/a&gt;) set out to teach us about design thinking, and how it’s important for any project. The main points that I took away from his talk were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visual design is only a small part of design.&lt;/li&gt;
  &lt;li&gt;UX research is not strictly academic or scientific – iterate quickly and rely on feedback to get the best results in the shortest time.&lt;/li&gt;
  &lt;li&gt;Embrace constraints to get the most out of a situation. Design is harder when you have a green field to work in – if you have constraints, don’t fight against them, use them for inspiration.&lt;/li&gt;
  &lt;li&gt;Everyone is a designer – if you’ve ever been on a project without a designer, it was you.&lt;/li&gt;
  &lt;li&gt;Always ask if the current approach is the best use of business capability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;functional-programming-for-fun-and-profit&quot;&gt;Functional Programming for Fun and Profit&lt;/h2&gt;

&lt;p&gt;Next up was James Ottoway (&lt;a href=&quot;https://twitter.com/jms_&quot; title=&quot;James Ottaway (jms_) on Twitter&quot;&gt;@jms_&lt;/a&gt;) with a good intro to functional programming. He started out by explaining declarative languages and reactive programming, as well as DSLs and closures and how they can be used to cut complexity.&lt;/p&gt;

&lt;p&gt;Declarative languages focus on expressing the logic of a computation, not how to carry out that computation. Regular expressions, Chef/Puppet configuration files, and SQL were all used as examples of declarative languages. In James’s words:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We’re expressing what, not how. And that’s a good thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Expressing what you want to do (and not how it must be done) frees up the compiler/interpreter to make decisions about implementation at runtime, and eases the burden on you as a programmer.&lt;/p&gt;

&lt;p&gt;When talking about reactive programming, James used Excel (everyone’s favourite spreadsheet application) as an example of a reactive program. This is a really simple analogy which I think helped everyone grasp the idea of reactive programming quickly. He also pointed out that the windows GitHub client is built using reactive programming (using &lt;a href=&quot;http://www.reactiveui.net/&quot; title=&quot;ReactiveUI&quot;&gt;ReactiveUI&lt;/a&gt; from what I can see).&lt;/p&gt;

&lt;p&gt;As someone who’s trying to learn Haskell at the moment, this section about of this talk about closures was interesting to me. Closures aren’t something that I was seeing in Haskell, perhaps because I’m still battling with unfamiliar syntax (turns out they’re pretty much everywhere). A closure is just a function together with a referencing environment, and they’re pretty essential for functional programming.&lt;/p&gt;

&lt;h2 id=&quot;business-analysis&quot;&gt;Business Analysis&lt;/h2&gt;

&lt;p&gt;After lunch we heard about the life of a BA from Cathie Hagen (&lt;a href=&quot;https://twitter.com/catherist&quot; title=&quot;Cathie Hagen (catherist) on Twitter&quot;&gt;@catherist&lt;/a&gt;) and Jiangmei Kang. BAs are an integral part of every stage of a project, and use their place as a bridge between the client and the developers to ensure that value is delivered to the client. The following is a photo I took of the board used to explain the many aspects of work as a BA, I think it says more than I can:&lt;/p&gt;

&lt;figure&gt;
    &lt;a href=&quot;/public/images/2013/10/TW-LevelUp-Business-Analysis.jpg&quot;&gt;
        &lt;img class=&quot;lozad&quot; data-src=&quot;/public/images/2013/10/TW-LevelUp-Business-Analysis.jpg&quot; alt=&quot;TW LevelUp - Business Analysis&quot; /&gt;
    &lt;/a&gt;
    
    &lt;figcaption&gt;
    (Sorry about the poor quality – the projector turned on for the next talk just as I was taking this picture)
    &lt;/figcaption&gt;
    
&lt;/figure&gt;

&lt;h2 id=&quot;user-testing&quot;&gt;User Testing&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Why build something that people don’t want to use? It’s 2013, doing that is a waste of humanities potential.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pete Chemsripong gave a great talk about the importance of user testing. Speed is important for user testing and ideally
should be a daily thing. Every feature that you’re working on in a project should be validated by a user (this agrees
with what Ben said in the design talk).&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;helping-you-get-your-first-job&quot;&gt;Helping you get your first job&lt;/h2&gt;

&lt;p&gt;The last presentation before the keynote was by Jean D’amore (&lt;a href=&quot;https://twitter.com/jeandamore&quot; title=&quot;Jean D&apos;amore (jeandamore) on Twitter&quot;&gt;@jeandamore&lt;/a&gt;) with an entertaining talk on how to land your first job in IT. The talk introduced job hunting as a game where you can’t control everything, but what you can control can make all the difference. He split the journey into seven steps, each accompanied by a great movie reference &amp;amp; quote. Hopefully the slides will be made available as I didn’t get everything down, but what follows is my summary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Yourself (The Last Samurai)
    &lt;ul&gt;
      &lt;li&gt;Improve the environment by working on yourself.&lt;/li&gt;
      &lt;li&gt;Do: know your boundaries, be versatile, stretch yourself, maintain balance, listen, commit to projects, be willing to sacrifice, learn/do new things&lt;/li&gt;
      &lt;li&gt;Don’t: underestimate yourself, thing you’re alone, deny the challenge, limit the horizon&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The Search (An Unexpected Journey)
    &lt;ul&gt;
      &lt;li&gt;The search will change you&lt;/li&gt;
      &lt;li&gt;Do: know what you seek, choose a domain, know the employer, ask about graduate programs/training, keep your LinkedIn (and internet presence in general) up to date, favour simple job ads (i.e. not ads that list every skill under then sun – you often need to be a specialist before you can generalise)&lt;/li&gt;
      &lt;li&gt;Don’t: dismiss too quickly, use recruitment agencies, work on projects you don’t agree with (everything you do has an impact and will impact you), waste too much time searching on-line (do spend more time talking to people)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Your CV (The Colour of Money)
    &lt;ul&gt;
      &lt;li&gt;Do: PDF it!, make it unique, know what’s on it, web design it (use web design principles – e.g. readability, don’t cram everything in), make it one page, get friends to read it, start with skills over education&lt;/li&gt;
      &lt;li&gt;Don’t: lie/exaggerate, rush it, use ‘bullshit bingo’ words (except in a few cases where it’s in the ad – in this case, always explain and give examples)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Applying (Close Encounters of the Third Kind)
    &lt;ul&gt;
      &lt;li&gt;You need to understand and be understood&lt;/li&gt;
      &lt;li&gt;Do: strike with precision, add a cover letter, apply to people (not computers), customise your CV, wait, follow-up, be organised&lt;/li&gt;
      &lt;li&gt;Don’t: bulk apply (do apply to at most 5 organisations at once – it becomes too hard to keep track of what you’re doing otherwise)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Interviews (Gattaca)
    &lt;ul&gt;
      &lt;li&gt;Little things are often the most important. For example, be good to everyone at the company.&lt;/li&gt;
      &lt;li&gt;Do: look clean and tidy, research the company &amp;amp; their interview process, arrive early, know who you are and why you’re there, know what you’ll be asked, listen, ask relevant questions, be humble and curious, know your stuff (especially your résumé)&lt;/li&gt;
      &lt;li&gt;Don’t: be afraid to ask for clarification, lower your guard until you’re clear of the building (i.e. do treat every moment you’re in/near their offices as part of the interview), ask how you did at the interview, ask about time/money when you’re after your first job, leave your phone on, have alcohol (even if offered), go if you’re sick (you need to be 100%, and the interviewers will understand)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Hearing Yes/No (The Hurricane)
    &lt;ul&gt;
      &lt;li&gt;Don’t be afraid of failing and keep bouncing back&lt;/li&gt;
      &lt;li&gt;Do: take your chance to explore/re-evaluate, take risks, trust your instinct, understand that this is one step is a career&lt;/li&gt;
      &lt;li&gt;Don’t: burn bridges, take it personally, rush to accept, say you’re waiting on another offer&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;First Day (City Hall)
    &lt;ul&gt;
      &lt;li&gt;Make a difference and work where you’re satisfied. Focus on employers that give you the upper parts of &lt;a href=&quot;http://en.wikipedia.org/wiki/Maslow&apos;s_hierarchy_of_needs&quot; title=&quot;Maslow&apos;s hierarchy of needs&quot;&gt;Maslow’s hierarchy of needs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Do: learn names, go to social events, pair, do what you’re told, be helpful, learn the ropes step by step, leave if you don’t like it after a month of so&lt;/li&gt;
      &lt;li&gt;Don’t: panic, try to change things quickly, cold shoulder anyone&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;closing-keynote-who-are-you-where-are-you-going-and-how-will-you-get-there&quot;&gt;Closing Keynote: Who are you, where are you going, and how will you get there?&lt;/h2&gt;

&lt;p&gt;The closing keynote by Chad Renando (&lt;a href=&quot;https://twitter.com/ChadRenando&quot; title=&quot;Chad Renando (ChadRenando) on Twitter&quot;&gt;@ChadRenando&lt;/a&gt;) followed on nicely from the presentation from Jean, and was really a step back, focussing on making the most of who you are, being clear about where you are going, and being intentional about how you can get there.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Every man invents a story for himself – which he often, and with great cost to himself – takes to be his life.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Chad used this quote from Max Frisch as a way of explaining that you create your own story, but you should never think that it can’t be changed or even completely rewritten.&lt;/p&gt;

&lt;p&gt;You need to understand yourself to understand how you will work with others – are you more practical or creative? Do you approach things in an analytical way or listen to your beliefs? Are you structured or flexible? Learn what your &lt;a href=&quot;https://en.wikipedia.org/wiki/Values_in_Action_Inventory_of_Strengths&quot; title=&quot;Values in Action Inventory of Strengths - Wikipedia&quot;&gt;signature strengths&lt;/a&gt; are and use those to create a mission statement, as your strengths are the things that make you feel alive. At the same time, look out for the strengths that you rank poorly in.&lt;/p&gt;

&lt;p&gt;Create goals (what is your 9-day plan? your 120-day plan?) that align with your strengths, but don’t think that these goals are set in stone. Use goals as a way to direct yourself, not as measures of success. This allows you to iterate on your goals and improve them as you learn more about yourself.&lt;/p&gt;

&lt;p&gt;Chad finished the main part of his talk with his axioms from life in a digital studio:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ask questions&lt;/li&gt;
  &lt;li&gt;Focus on resolving process conflict, not relationship conflict&lt;/li&gt;
  &lt;li&gt;There are things that are understandable, but not acceptable – don’t get the two confused&lt;/li&gt;
  &lt;li&gt;Everyone is generally doing the best they can&lt;/li&gt;
  &lt;li&gt;There is no fault, only cause&lt;/li&gt;
  &lt;li&gt;Every conversation we have is with ourselves, and sometimes they involve others&lt;/li&gt;
  &lt;li&gt;If you want to lead others, lead yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;p&gt;The day covered a range of topics and gave me a lot to think about. One point that appeared a couple of times throughout the day (and which Chad reiterated at the end of his keynote) is how important it is to get involved with your community. It allows you to grow your network, get references and learn. I can’t agree more, I have learnt so much and met lots of interesting people by attending the &lt;a href=&quot;http://yowconference.com.au&quot; title=&quot;YOW! | Australian Developer Conference&quot;&gt;YOW! conference&lt;/a&gt;, &lt;a href=&quot;http://yowaustralia.com.au/general/yownights.html&quot; title=&quot;YOW! Nights&quot;&gt;YOW! nights&lt;/a&gt;, and the &lt;a href=&quot;http://www.meetup.com/Brisbane-Functional-Programming-Group/&quot; title=&quot;BFPG&quot;&gt;BFPG&lt;/a&gt; &amp;amp; &lt;a href=&quot;http://www.meetup.com/Brisbane-GPU-Users/&quot; title=&quot;Brisbane GPU Users (Brisbane ) - Meetup&quot;&gt;Brisbane GPU Users&lt;/a&gt; meetups (there are tons of similar user groups in Brisbane – I guarantee you won’t regret attending one of their meetups!). Another way to get involved in the broader community while sharpening your skills is volunteering – there are plenty of non-profits that could use help with IT. Or, if you have an idea/are working on a start-up, &lt;a href=&quot;http://www.rivercitylabs.net/&quot; title=&quot;River City Labs&quot;&gt;River City Labs&lt;/a&gt; is building an amazing community of like-minded people.&lt;/p&gt;

&lt;p&gt;Thanks again to ThoughtWorks for running this mini-conference – you’ve done a great job of inspiring this IT undergrad! More about ThoughtWorks LevelUp can be found on Twitter (&lt;a href=&quot;https://twitter.com/TW_LevelUp&quot; title=&quot;LevelUp on Twitter&quot;&gt;@TW_LevelUp&lt;/a&gt;) and &lt;a href=&quot;https://www.facebook.com/ThoughtworksLevelUp&quot; title=&quot;ThoughtWorks Level Up&quot;&gt;Facebook&lt;/a&gt;.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Kevlin Henney on code comments</title>
    <link href="/2013/10/kevlin-henney-a-common-fallacy/"/>
    <updated>2013-10-16T00:00:00+00:00</updated>
    <id>/2013/10/kevlin-henney-a-common-fallacy/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;A common fallacy is to assume authors of incomprehensible code will somehow be able to express themselves lucidly and clearly in comments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;http://kevlin.tel/&quot; title=&quot;kevlin.tel&quot;&gt;Kevlin Henney&lt;/a&gt; (original tweet &lt;a href=&quot;https://twitter.com/KevlinHenney/status/381021802941906944&quot; title=&quot;Kevlin Henney - A common fallacy is to assume ...&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;There are some interesting responses, pointing out that comments are great for references and in-line diagrams, and sometimes necessary for code that has been restructured to improve performance (although creating difficult to read code solely for performance reasons is a separate issue).&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>John Carmack on type systems</title>
    <link href="/2013/10/john-carmack-on-type-systems/"/>
    <updated>2013-10-04T00:00:00+00:00</updated>
    <id>/2013/10/john-carmack-on-type-systems/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;blockquote&gt;
  &lt;p&gt;It’s just amazing how many mistakes [are made] and how bad programmers can be. Everything that is syntactically legal, that the compiler will accept, will eventually wind up in your code base. And that is why I think static typing is so valuable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/John_Carmack&quot; title=&quot;John D. Carmack&quot;&gt;John Carmack&lt;/a&gt; (full talk &lt;a href=&quot;http://youtu.be/1PhArSujR_A?t=15m47s&quot; title=&quot;John Carmack&apos;s keynote at Quakecon 2013 (Part 4)&quot;&gt;here&lt;/a&gt; – note this link jumps to this quote – part one of the keynote is &lt;a href=&quot;http://youtu.be/eNWAcEu1jpU?t=15m12s&quot; title=&quot;John Carmack&apos;s keynote at Quakecon 2013 (Part 1)&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Pretty much sums up how I feel about the static v. dynamic debate for anything other than very short-lived prototypes.&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>Don’t fear the Monad</title>
    <link href="/2013/10/dont-fear-the-monad/"/>
    <updated>2013-10-03T00:00:00+00:00</updated>
    <id>/2013/10/dont-fear-the-monad/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I recently watched Brian Beckman’s &lt;a href=&quot;http://channel9.msdn.com/shows/Going+Deep/Brian-Beckman-Dont-fear-the-Monads/&quot;&gt;Don’t fear the monad&lt;/a&gt; talk (YouTube version &lt;a href=&quot;http://www.youtube.com/watch?v=ZhuHCtR3xq8&quot;&gt;here&lt;/a&gt;) and thought it was a really good explanation of functions, monoids &amp;amp; monads and why they’re a useful way to master complexity.&lt;/p&gt;

&lt;p&gt;I recommend it to anyone who’s starting to look at functional programming. Here are some of the key points I took away from the talk:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Functions are data
    &lt;ul&gt;
      &lt;li&gt;A function takes an argument(/s) and returns a value, and always returns the same result for the same inputs&lt;/li&gt;
      &lt;li&gt;Think of a function as a table lookup – the table is the data&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Functional programming is a style that can be used in almost any language
    &lt;ul&gt;
      &lt;li&gt;But some languages make it easier than others&lt;/li&gt;
      &lt;li&gt;First class functions (or at least lamdbas) are a must have&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Complexity is killing software developers – we need to control it
    &lt;ul&gt;
      &lt;li&gt;The best way to control complexity is to put functions into groups where things are disciplined, and where they can be composed in arbitrary ways&lt;/li&gt;
      &lt;li&gt;Build complexity out of simplicity by composing things&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;A monad adds some data to a value, and the implementation of the bind operator defines how that data interacts&lt;/li&gt;
  &lt;li&gt;If you want to add a feature, you shouldn’t even have to know what you’re going to interact with
    &lt;ul&gt;
      &lt;li&gt;Using monads means the interaction is already built into the structure&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You don’t need to know what a monad does
    &lt;ul&gt;
      &lt;li&gt;So long as it follows the rules, it can have arbitrary side effects&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another interesting part was Brian’s reasoning about why functional programming is a ‘hard sell’:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Immediately upon the foundation of computing, the world split into two camps – the bottom up camp and the top down camp.&lt;/p&gt;

  &lt;p&gt;The bottom up camp is typified by Turing machines – “let’s start with the hardware and add abstraction as we need it to get close to the mathematics, but never at the expense of performance”. That gave rise to FORTRAN, C, C++, Pascal, Java, C# … all of those languages are in that tradition.&lt;/p&gt;

  &lt;p&gt;The top down crowd says “let’s start with the mathematics and subtract abstractions to get down to the machine, sometimes at the expense of performance”. That tradition starts with lambda calculus … and only subtracts abstraction when it is convenient to do so. That’s the tradition that gave rise to ALGOL, Lisp, Smalltalk, ML, Haskell and all these languages that have reputations of being slow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As most programmers are familiar with the bottom up way of doing things and the two approaches come from very different origins, it can be hard to convince a bottom up programmer of the benefits of the ‘top down’ approach. It can be even harder to pick up functional programming once you’ve resigned to giving it a try.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[The top-down crowd] are saying “don’t go to the hardware so early, you’ll lock yourself into irreversible design choices”. [The bottom-up crowd] are saying “don’t give me all this math, I can’t handle garbage collection, or function calls or whatever it is that’s getting in the way of my performance, I need every ounce of performance the hardware can give me. And I’m willing to write software into the wee hours of the morning to get it”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last sentence here is what stands out to me – as software gets more complex, it seems that bottom up programming is going to require more and more time working in the wee hours of the morning to get the desired performance and functionality.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Maybe Haskell …</title>
    <link href="/2013/09/maybe-haskell/"/>
    <updated>2013-09-14T00:00:00+00:00</updated>
    <id>/2013/09/maybe-haskell/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;After reading &lt;a href=&quot;http://learnyouahaskell.com/&quot; title=&quot;Learn You a Haskell&quot;&gt;Learn You a Haskell&lt;/a&gt; on and off over the past fortnight and watching a couple of Erik Meijer’s &lt;a href=&quot;http://channel9.msdn.com/Series/C9-Lectures-Erik-Meijer-Functional-Programming-Fundamentals&quot; title=&quot;Erik Meijer - Functional Programming Fundamentals&quot;&gt;Functional Programming Fundamentals&lt;/a&gt;,
I finally got around to installing the Haskell platform and firing up GHCi.&lt;/p&gt;

&lt;p&gt;After a couple of hours of implementing the simple functions scattered throughout LYAH, I was up to &lt;a href=&quot;http://learnyouahaskell.com/recursion#quick-sort&quot; title=&quot;Learn You a Haskell - Recursion&quot;&gt;implementing quick sort&lt;/a&gt;.
Given the number of times I’ve seen this example, I’m not going to reproduce it here, but it’s pretty amazing &lt;sup&gt;&lt;a href=&quot;#f1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;One of the main things I noticed was that after two hours of writing code in a language I’d never used, I’d produced
&lt;strong&gt;zero run time errors&lt;/strong&gt;. There were plenty of compile errors, but that’s to be expected – especially given I was
using an editor that was inserting tabs in a language with significant white space (which, by the way, makes for fun
times when unfamiliar with Haskell compiler errors). I know what kind of error I would prefer to deal with.&lt;/p&gt;

&lt;p&gt;So far I’m liking Haskell, and I think it’s a huge shame that there is only one functional programming course at
my university (&lt;a href=&quot;http://www.uq.edu.au/study/course.html?course_code=COMP1024&quot; title=&quot;Conceptual Foundations of Computer Programming (COMP1024)&quot;&gt;COMP1024&lt;/a&gt;), which isn’t available to most dual degree students.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: COMP1024 hasn’t been offered since 2010.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a name=&quot;f1&quot;&gt;&lt;/a&gt;1. I know this isn’t ‘true’, in-place, high performance quick sort, but in how many other languages can you write a readable, generic sorting algorithm in 6 lines of code?&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>VirtualBox + Dell laptop VT-x issues</title>
    <link href="/2013/08/virtualbox-dell-laptop-vt-x-issues/"/>
    <updated>2013-08-15T00:00:00+00:00</updated>
    <id>/2013/08/virtualbox-dell-laptop-vt-x-issues/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;I recently had to use a VM for a uni project, and needed to have access on my laptop &amp;amp; desktop. I haven’t used a VM on my laptop in a
while, but didn’t expect to see the following error message from VirtualBox (4.2.16):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;VT-x features locked or unavailable in MSR.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’ve used x64 hosts before with no problems, but I guess my BIOS settings were reverted for some reason (using a Dell laptop
with Intel PM45 chipset).&lt;/p&gt;

&lt;p&gt;So thinking to myself that this should be an easy fix, I rebooted, enabled VT-x and restarted, but I received the same error
message. No amount of changing BIOS/VirtualBox settings, rebooting or otherwise reconfiguring would make this message go away.&lt;/p&gt;

&lt;p&gt;I eventually read that it’s sometimes &lt;strong&gt;necessary to power down and physically disconnect the machine from power to properly
enable VT-x&lt;/strong&gt;. This solved my problem – I decided to make a note of it here to hopefully help someone else in the same situation.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Ubuntu 12.10 – Transmission fails to connect to HTTPS trackers</title>
    <link href="/2013/01/ubuntu-12-10-transmission-fails-to-connect-to-https-trackers/"/>
    <updated>2013-01-10T00:00:00+00:00</updated>
    <id>/2013/01/ubuntu-12-10-transmission-fails-to-connect-to-https-trackers/</id>
    <category term="software-tech" label="Software/Tech"></category>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.transmissionbt.com/&quot; title=&quot;Transmission&quot;&gt;Transmission&lt;/a&gt;, the BitTorrent client installed by default in Ubuntu seems to have an issue with connecting to trackers using HTTPS at the moment.&lt;/p&gt;

&lt;p&gt;After Transmission failed to connect to a tracker using HTTPS, I went searching and found this &lt;a href=&quot;https://bugs.launchpad.net/ubuntu/+source/gnutls26/+bug/937537&quot; title=&quot;libgnutls26 2.12.14 breaks SSL tracker support in Transmission&quot;&gt;bug report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The steps there are pretty simple and worked well for me:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Close Transmission&lt;/li&gt;
  &lt;li&gt;Download the .deb for updated libgnutls26 from &lt;a href=&quot;http://packages.debian.org/wheezy/libgnutls26&quot;&gt;here&lt;/a&gt; (bottom of page – choose your architecture then mirror)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install using&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; dpkg -i (package name).deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Restart Transmission&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;UPDATE: It looks like this is now fixed, so running&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;should get it working again for you.&lt;/p&gt;

</content>
  </entry>
  

</feed>
