<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Chris James - Software developer</title>
    <link>https://quii.dev</link>
    <description>Posts on software development and other things</description>
    <managingEditor>qui666@gmail.com (Chris James)</managingEditor>
    <pubDate>Tue, 10 Mar 2026 15:03:16 +0000</pubDate>
    <item>
      <title>The weight of AI on engineers</title>
      <link>https://quii.dev/The_weight_of_AI_on_engineers</link>
      <description>&lt;h2&gt;Accountability has a weight limit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If the AI deletes all your business-critical data, &lt;strong&gt;you can&#39;t fire the AI&lt;/strong&gt;. If an AI controlled missile launcher accidentally shoots an ally, you can&#39;t send the AI to prison. &lt;em&gt;AI can act, but only humans can be accountable&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As a rhetorical device for this post, let&#39;s assume that a single engineer &lt;em&gt;in the old days&lt;/em&gt; could complete one story a day, but now they can, and are expected to do 10; because AI makes writing code and building systems 10x faster, right?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Of course, measuring productivity by lines of code per day is stupid and flawed, and user stories have a similar problem. A user story &lt;em&gt;should&lt;/em&gt; be valuable, but it might not be. Sometimes our knowledge can be imperfect, and not quite what the user wants, or they could be catastrophically wrong. (See: &lt;a href=&#34;https://en.wikipedia.org/wiki/Mars_Climate_Orbiter&#34;&gt;the $327m Mars Climate Orbiter&lt;/a&gt;, lost because one team used metric units and another used imperial.)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Is it realistic though for an engineer to be accountable for 5-10x the amount of change they were dealing with before? How can they possibly understand 10 user stories, and the code that was written to fulfil the requirements. Does that sound realistic?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The AI maximalists argue you no longer &lt;em&gt;need&lt;/em&gt; to understand the code, just focus on the outcomes and let the AI deal with that weird code stuff. But nonetheless, whoever is accountable has to understand &lt;em&gt;how the system will behave&lt;/em&gt;; and that&#39;s not abstract: would you &lt;strong&gt;really&lt;/strong&gt; be comfortable taking accountability for something like the &lt;a href=&#34;https://en.wikipedia.org/wiki/Therac-25&#34;&gt;Therac-25&lt;/a&gt; (a radiation therapy machine whose software bugs delivered fatal overdoses to patients) if it was generated entirely from a prompt, &lt;em&gt;without understanding medicine?&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;We&#39;ve been solving the wrong problem&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The code was never the bottleneck. Not a new take, I appreciate. Pedro Tavares &lt;a href=&#34;https://ordep.dev/posts/writing-code-was-never-the-bottleneck&#34;&gt;put it well recently&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The marginal cost of adding new software is approaching zero, especially with LLMs. But what is the price of understanding, testing, and trusting that code? Higher than ever.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Now people believe reviewing is the bottleneck. What can we do? Every day stories of teams with 10s, 100s of pull requests stuck in review.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In truth, reviewing was a bottleneck for teams before the AI boom, they just didn&#39;t realise it. Many companies that adopt a &lt;a href=&#34;https://quii.dev/Reduce_WIP_by_practicing_trunk-based_development,_rather_than_pull_requests&#34;&gt;pull-request model&lt;/a&gt; with individual contributors &lt;em&gt;created&lt;/em&gt; a bottleneck, but it was one of their own doing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To deal with this, techniques from &lt;a href=&#34;https://www.amazon.co.uk/Extreme-Programming-Explained-Embrace-Change/dp/0321278658&#34;&gt;extreme programming&lt;/a&gt; (XP) are having somewhat of a renaissance, even if people don&#39;t want to admit it. XP Explained was published in 1999.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Hey everyone! I&#39;ve invented spec-driven development, totally a new thing, buy my book!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;— AI influencer, 2026&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These techniques will help, breaking problems down into smaller pieces, encoding small behaviour changes in automated tests reduces risk and cognitive load, but it still feels like it&#39;s attacking the wrong problem, it&#39;s treating a symptom, not the cause. Again, can a human realistically, deeply understand 10, albeit smaller problems every day?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Presence in the problem&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;My teams do pair programming. Where review is an ongoing part of the process. Two of you are in the context together. You might do an informal review together before committing, but it is nothing like the pull request model where you must read someone else&#39;s git diffs, out of context, when you have a spare 30 minutes. So, for my teams &lt;em&gt;reviewing wasn&#39;t a bottleneck&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Two humans pairing with an AI and watching what it does, &lt;em&gt;does not feel like pair programming&lt;/em&gt;, I think we might look back on this as a daft moment. Unthinkingly using the same tool or technique in a different context is often a bad decision. With pairing, it&#39;s like you&#39;ve introduced the worst part of pair programming; the demanding, present, high-energy way of work, with the boredom and difficulty of looking at git diffs written by someone else.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you&#39;re pairing, or if you&#39;re writing code by yourself &lt;em&gt;the engineer&#39;s presence is in the problem, not just the solution&lt;/em&gt;. The code is a manifestation of your business domain, it represents your business, and how it should behave. When you&#39;re writing code, you&#39;re trying to add capability to the business, or change how it works. Doing this, &lt;strong&gt;helps you understand it&lt;/strong&gt;, but now with AI writing the code, the human is taken out of this process.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There&#39;s a pattern every engineer recognises. A stakeholder comes in confident: &amp;quot;it&#39;s simple, I know exactly how it should work.&amp;quot; And on the surface, it is simple. But the moment you start building, the gaps appear. What happens when the user has two accounts? What does &amp;quot;current&amp;quot; mean when the time zone changes? These aren&#39;t edge cases, they&#39;re the domain, and they only reveal themselves under the pressure of implementation. &lt;em&gt;This is the engineering.&lt;/em&gt; Not the code, the thinking. The code is just what&#39;s left behind when the thinking is done. Coding agents don&#39;t help here, if anything they let you paper over the gaps faster.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Review is still necessary. The question is what good review looks like when the code wasn&#39;t written by a human. Reading git diffs was always a blunt instrument, but we tolerated it because the human who wrote the code had already done the hard cognitive work; the diff was just a record of their thinking. When an AI writes the code, that thinking never happened on the human side. The diff is all there is, and it tells you surprisingly little about whether the system now behaves correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;diff&#xA;+ const r = await db.query(`SELECT * FROM orders o LEFT JOIN users u ON&#xA;+   u.id = o.user_id LEFT JOIN products p ON p.id = o.product_id WHERE&#xA;+   o.status NOT IN (&#39;cancelled&#39;,&#39;refunded&#39;) AND (u.flags &amp;amp; 0x4) = 0&#xA;+   AND p.region = $1 GROUP BY o.id, u.id HAVING sum(o.qty * p.price)&#xA;+   &amp;gt; $2 ORDER BY o.created_at DESC`, [ctx.region, threshold])&#xA;+ if (r.rows.length) await notify(r.rows.map(x =&amp;gt; transform(x, opts)))&#xA;&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;LGTM&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Engineers don&#39;t think in text files. We build mental models of flows, of state, of how components talk to each other. Maybe the right review primitive isn&#39;t a diff at all. Sequence diagrams, visual system maps, behaviour traces -- tools that show you what the system &lt;em&gt;does&lt;/em&gt; rather than what the code &lt;em&gt;says&lt;/em&gt;. This feels like an open problem the industry hasn&#39;t seriously tackled yet, and I suspect whoever cracks it will matter more to the future of AI-assisted engineering than whatever coding agent is flavour of the month.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Left of dev&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So, if the AI has freed up time, what&#39;s it freed for? I think, given the cognitive burden, perhaps churning out more stories per day is not the right approach. How about the engineers focus on making stories valuable in the first place. The stuff that happens &amp;quot;left of dev&amp;quot;. Sitting with users and watching them use your product, taking part in research, spending more time with stakeholders and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Perhaps the real unlock of AI isn&#39;t this &amp;quot;10x&amp;quot; thing, it&#39;s that engineers finally have time to deeply understand what they&#39;re building, and why. That may result in some real productivity gains, more valuable stories gained from deeper insights; and it helps the people working on these systems feel more comfortable with the accountability on their shoulders.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Some nice feedback on LGWT</title>
      <link>https://quii.dev/Some_nice_feedback_on_LGWT</link>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.linkedin.com/in/william-martin-41400517/&#34;&gt;William Martin&lt;/a&gt; forwarded me some written feedback on &lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests&#34;&gt;Learn Go With Tests&lt;/a&gt; from &lt;a href=&#34;https://www.linkedin.com/in/kynan-ware/?originalSubdomain=ca&#34;&gt;Kynan Ware&lt;/a&gt; which made my day.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I get a lot of friendly feedback from people on the work, but this is one of those where the author has taken the time to&#xA;explain why they enjoyed the book more specifically.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Before reading Learn Go With Tests, I read a Go different book that only had a chapter on the standard library’s testing suite. To say Learn Go With Tests expanded on that chapter would be an understatement. Getting hands on with the standard library and how it works was great and informative. Keep in mind that I do not have really any background in testing anyways, so I needed to be told both what features and patterns exist in a general sense and how they are used; Learn Go With Tests did just that and more.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I enjoyed seeing the TDD feedback loop in a hands-on way with concrete examples. The author took their time to explain why TDD is valuable in a “show, don’t tell” way.&#xA;&lt;strong&gt;Initially, the TDD loop seemed tedious and monotonous&lt;/strong&gt;, but as I progressed through the book past the simple examples and into more complex territory, I found it to be actually fun, interesting, and very productive to get instant feedback on your work.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;(The emphasis is mine). I have spent a lot of time directly and indirectly (e.g the book) coaching TDD and this mental leap is often the hardest one. Many people find it boring, many find it &amp;quot;unrealistic&amp;quot; and bemoan how TDD tutorials are often too simplistic, and don&#39;t apply in the real world.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;TDD does work in the real world, but it takes time and practice. In my mind, one goal of TDD is breaking down work well enough so your real work, feels as simple as the examples you learned it with.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;This was new to me (surprise!), but I like the idea that TDD is a design tool very much. I’m not going to repeat or summarize the book’s details on why or how it is used as a design tool, but I’ll just say that I ingested this idea and vibe with it very much.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&#39;s gratifying this message is coming through to people who read the book, because this is often such a missed point of TDD. Sadly, many believe TDD is merely about achieving test coverage, but in &lt;a href=&#34;https://quii.dev/The_Why_of_TDD&#34;&gt;The Why of TDD&lt;/a&gt; I write at length how it is so much bigger than that.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The author was also particularly good at answering questions that might come up as they come up. The moment I had a question in my mind, the next sentence addressed it. I thought it was beautifully written.&#xA;I didn’t have a place for this point in another heading, but I also wanted to mention how much I enjoyed just the overall introduction to testing patterns in general.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 21 Sep 2024 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Learn Go with Tests reaches 20k stars</title>
      <link>https://quii.dev/Learn_Go_with_Tests_reaches_20k_stars</link>
      <description>&lt;p&gt;I made &lt;a href=&#34;https://github.com/quii/learn-go-with-tests/commit/324ee30537bb0d0354f1c6b33daa68d9937b04b6&#34;&gt;The first commit for Learn Go with Tests&lt;/a&gt; (&lt;a href=&#34;https://github.com/quii/learn-go-with-tests&#34;&gt;LGWT&lt;/a&gt;) on the 2nd of March 2018. I was hungover and frustrated at the lack of high-quality test-driven development articles I had seen in the Go community, so I decided to give it a Go.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst I understand that GitHub stars &lt;em&gt;don&#39;t mean anything&lt;/em&gt;, they are still an indicator that the project is well received. I&#39;m not going to engage in false modesty; I&#39;m proud of this project; it&#39;s probably one of the best things I&#39;ve accomplished in my career.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://star-history.com/#quii/learn-go-with-tests&amp;amp;Date&#34;&gt;&lt;img src=&#34;https://api.star-history.com/svg?repos=quii/learn-go-with-tests&amp;amp;type=Date&#34; alt=&#34;Star History Chart&#34; /&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However, it would be wrong not to mention that it has been a community effort driven by &lt;strong&gt;212 other contributors&lt;/strong&gt;. I truly appreciate every contribution you have made.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With each star, fork, and contribution, the project&#39;s reach has expanded, reaching corners of the world I could have imagined. Between 2018 and now, there have been &lt;strong&gt;1299 more commits&lt;/strong&gt; and &lt;strong&gt;translated into &lt;a href=&#34;https://github.com/quii/learn-go-with-tests/commit/324ee30537bb0d0354f1c6b33daa68d9937b04b6&#34;&gt;five other languages&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The repository&#39;s impact has even been recognised beyond the GitHub platform, with mentions in articles, forums, books and tech conferences.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The rest of this post reflects on the experience, lessons learned, and plans.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; Be nice&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I never intended to write much more beyond the hello world chapter, but when my friend messaged me saying I was top of the &lt;em&gt;orange site&lt;/em&gt;, I couldn&#39;t quite believe it. The comments were positive, and my GitHub feed was alive for the first time. This drove me to keep writing more; without the positive feedback, it&#39;s unlikely LGWT would exist at all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The feedback confirmed for me that the idea was a good one. I could use Go, a simple, easy-to-understand language and ecosystem, as a vehicle for teaching TDD properly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The takeaway here is, &lt;u&gt;be nice&lt;/u&gt;! If you use something someone provides or read something interesting, tell them. It will mean a lot and may act as a motivator for them to keep them driving forward.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Learning by writing learning go with tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I wouldn&#39;t describe myself as a Go expert when I started the project. I only had a few years of experience with Go, although I did have around ten years of software development experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whether you&#39;re writing open-source code or blogging, if it gets attention, you will have people giving you feedback on your work. &lt;em&gt;Sometimes&lt;/em&gt; it is done in a constructive, friendly manner, and some people are just angry someone said something wrong on the internet. Sadly, you have to build a bit of resiliency for this, but I definitely learned a lot &lt;strong&gt;from&lt;/strong&gt; the community and hopefully taught a lot back to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve always relied on writing to organise my thoughts to communicate better, and the five years of LGWT have helped me practice this critical skill. Having to write these posts has helped my TDD coaching skills tremendously. I am a much better teacher of TDD as a result.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; Work in progress&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Delightfully, the Go language is very conservative concerning language design. This means the content I wrote five years ago is still broadly correct. Some tooling changes have happened (I try to resist adding stuff about that anyway), but the language is highly stable. As new features land or exciting additions to the standard library are made, I will always try to bring a chapter in to cover it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That said, I would hope by the time readers have made it to the end of the book, they have &lt;a href=&#34;https://en.wiktionary.org/wiki/give_a_man_a_fish_and_you_feed_him_for_a_day;_teach_a_man_to_fish_and_you_feed_him_for_a_lifetime&#34;&gt;learned how to fish&lt;/a&gt;. That&#39;s why you&#39;ll find the most recent chapters of LGWT, are not specific to Go, but more around software design and approaches.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To that end, I am working on a chapter called &amp;quot;Living without mocks&amp;quot;, which goes into contract testing, testing databases and some commentary on designing your software for testability, especially with respect to fast and accurate feedback loops. No promises when it&#39;ll be done, as I do have bills to pay and other hobbies to enjoy.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Learn &lt;code&gt;X&lt;/code&gt; with tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Many have requested that someone make equivalent resources for Rust, JavaScript and others. As I mentioned earlier, if I have done a good job with LGWT, you can read that and apply the same method for learning other things; you don&#39;t need someone to write something for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can find me using tests to try and get a handle on a few programming languages to varying levels of expertise at:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/learn-kotlin-with-tests&#34;&gt;Learn Kotlin with Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/learn-clojure-with-tests&#34;&gt;Learn Clojure with Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/learn-python-with-tests&#34;&gt;Learn Python with Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/learn-hyperscript-with-tests&#34;&gt;Learn HyperScript with Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/learn-elixir-with-tests&#34;&gt;Learn Elixir with Tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;They don&#39;t feature any commentary, just the code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would &lt;strong&gt;love&lt;/strong&gt; to write a &amp;quot;proper&amp;quot; book in the LGWT format sometime in the future. On my list of &amp;quot;maybe, one day, if I win the lottery and don&#39;t have to have a full-time job&amp;quot;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Learn Rust with Tests&lt;/li&gt;&#xA;&lt;li&gt;Learn Ocaml with Tests&lt;/li&gt;&#xA;&lt;li&gt;Learn Svelte with Tests&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;It&#39;s not a proper book.&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I do feel sad that I haven&#39;t gotten a physical book edited by a real publisher due to all this effort. Mainly to give to my parents as I think they would understand the accomplishment better!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have had a couple of publishers approach me, but none of them has been able to work with the constraint of keeping material open-source, which is understandable as they need to make money. Realistically, the only way to accomplish this dream is to find the time to do it again with a different programming language.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Comments&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In one final ego boost, I did some internet searches to try and dig up some pleasant comments for LGWT.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;One of the things that took my programming know-how to the next level was going through a Test Driven Development guide that used Golang&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/sudobunni/status/1604197697887641600&#34;&gt;Learn Go with Tests is incredible&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/quii&#34;&gt;@quii&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/jeroendee/status/1362273979801735168&#34;&gt;you&#39;ve written one of the best programming books I&#39;ve ever used. &amp;quot;Learn Go with Tests&amp;quot;. Enjoying it very much. Thank you.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/PenthaaPatel/status/1162005624982388736&#34;&gt;As a beginner, I found Learn Go with Tests extremely helpful. Thanks a lot&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/quii&#34;&gt;@quii&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;for putting up such great learning content! :)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=31164851&#34;&gt;Read and typed along with an early edition of this a few years back and it has continued to be one of my favorite technical tutorials of all time, far surpassing lots of other golang material that I&#39;ve paid money for.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=31169673&#34;&gt;I decided to learn and use Go for my recent job hunt, and this site was just the best. I used the structure of the code in the &amp;quot;build an application&amp;quot; section in every take home coding challenge I wrote.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://news.ycombinator.com/item?id=20704746&#34;&gt;Learn Go with Tests is the best programming language course I&#39;ve ever gone through.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;https://github.com/quii/learn-go-with-tests&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&#39;s all. Just sharing that the methodology worked so well. I felt like I could legitimately jump right into a Go developer team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;....&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I can&#39;t upvote this enough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am going through this course- and it is fabulous. Covers tests, and even though the topic names might seem easy or trivial(I mean there is only so many ways you can write loops or define arrays), they include a lot of &amp;quot;extras&amp;quot; that make it fun- for example one of the topics might include details about how to write doctests and docs, another one might introduce table driven tests and provide advice on when to use them. Overall it is great.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 18 Aug 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Practical ways to shift QA left</title>
      <link>https://quii.dev/Practical_ways_to_shift_QA_left</link>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;“Inspection to improve quality is too late, ineffective, costly. Quality comes not from inspection, but from the improvement of the production process.”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;― &lt;strong&gt;W. Edwards Deming,&lt;/strong&gt;&lt;a href=&#34;https://www.goodreads.com/work/quotes/553678&#34;&gt; Out of the Crisis&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Many prescribe shifting QA left, which sounds clever, but it&#39;s not very actionable advice, more an aspiration. This post describes concrete things quality assurance engineers can do to help increase quality and reduce waste within their teams.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;strong&gt;The QA role in a continuous delivery and deployment world&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;https://cloud.google.com/devops/state-of-devops/&#34;&gt;State of DevOps Report&lt;/a&gt; asserts that profitable, high-performing teams deploy software tens of times per day. The days of QAs signing off work before it is deployed are gone for elite teams.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even with feature flags to decouple feature release and software deployment, the &lt;em&gt;code&lt;/em&gt; is still being deployed, and it will affect the system&#39;s quality, even if it hasn&#39;t gone through the JIRA theatre of moving into the done column.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Nonetheless, quality is still essential! The report also asserts that high-performing teams have a low defect rate; throwing things into production and hoping for the best is insufficient. High-performing teams don&#39;t sink lots of time fixing bugs because the quality of their releases is excellent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s common for teams that are only releasing bi-weekly to have automated tests to give confidence that the system does what it&#39;s supposed to, which is good. However, as Deming said, this is still inspection after the work is done.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s an improvement; at least it&#39;s automated, but these tests are &lt;em&gt;rarely&lt;/em&gt; run in prod and &lt;strong&gt;say little about the system&#39;s quality&lt;/strong&gt;, just that it behaves in specific ways in certain conditions in a non-production environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We only really appreciate the quality of a system, when it is in production and used by real people. Beyond trivial systems, what you&#39;ll discover can be very unpredictable and interesting. This is when you &lt;em&gt;really&lt;/em&gt; start to understand the quality of your system and what needs improving.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The QA role must move away from inspection of features, which can be largely automated, and instead focus more on understanding what the system is doing in production.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;strong&gt;Why is quality important?&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Sounds obvious&lt;/em&gt;, but often teams (or management) make decisions to trade off quality for speed. This is a false economy. Speed and quality are correlated.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Quality is what helps teams continue to deliver&lt;/strong&gt;, especially over time.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The Accelerate authors have data that shows significant correlations with much more important things.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, organizations made up of high-performing teams, based on this model, make more money than orgs that don’t. Here is data that says that there is a correlation between a development approach and the commercial outcome for the company that practices it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;It also goes on to dispel a commonly held belief that “you can have either speed or quality but not both.” This is simply not true. Speed and quality are clearly correlated&lt;/strong&gt; in the data from this research.”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;~~ &lt;strong&gt;Dave Farley&lt;/strong&gt;, &lt;a href=&#34;https://www.amazon.co.uk/Modern-Software-Engineering-Really-Better/dp/0137314914&#34;&gt;Modern Software Engineering&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is too familiar a story for teams to struggle with bugs, support requests and other issues around quality, reducing their capacity to evolve their system further. Many teams will be in this situation, frustrated that they don&#39;t have enough time to further iterate on their system to respond to customer demands.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As with all things around agile, DevOps, etc., they all have their roots in lean manufacturing. Lean prescribes a zero-defect culture and &lt;strong&gt;reduces waste by increasing quality&lt;/strong&gt;. &lt;strong&gt;&lt;u&gt;By reducing waste, we increase our capacity to do valuable work for the customer&lt;/u&gt;&lt;/strong&gt;. This allowed Toyota et al. to outcompete their American competitors (who deferred quality checks to the &lt;em&gt;end&lt;/em&gt; of the assembly line), building cars more quickly and cheaply.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The cost of fixing an issue and its impact increases the further right in the process, and the longer it is in production. Shift-left means a team will catch problems sooner, reduce waste, and increase capacity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Teams should aim to have zero support requests landing on their plate. Too often, teams accept a &lt;a href=&#34;https://en.wikipedia.org/wiki/Normalization_of_deviance&#34;&gt;normalisation of deviance &lt;/a&gt;and become a &lt;a href=&#34;https://en.wikipedia.org/wiki/Boiling_frog&#34;&gt;boiling frog&lt;/a&gt;, losing their ability to iterate and improve the product they work on.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;A quick waste rant&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;As I mentioned in &lt;a href=&#34;https://quii.dev/The_ghost_of_Henry_Ford_is_ruining_your_development_team&#34;&gt;The Ghost of Henry Ford is ruining your development team&lt;/a&gt;, many managers think about lean in fairly short-sighted ways. They will focus on waste only through the lens of:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Only do work that generates &amp;quot;value&amp;quot;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This can take the form of:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Analysing stories very deeply, so no wasted effort is made on features that might not be valuable.&lt;/li&gt;&#xA;&lt;li&gt;Deprioritising any tasks around technical debt, toil, etc&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;u&gt;This does not work.&lt;/u&gt; Analysis paralysis is a form of waste in itself, and not letting teams improve the quality of their system also generates &lt;strong&gt;huge&lt;/strong&gt; waste.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Moving on...&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;strong&gt;Shifting QA left, and improvement of the process.&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The ultimate in shift-left are QAs influencing the formulation of user stories, where they are armed with a deep knowledge of how the system works, what problems commonly occur, its dependencies and so on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The QAs are equal partners in prioritisation discussion, raising issues that should be addressed, affecting the system&#39;s quality and producing waste.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;QAs often are too focused on the &amp;quot;outside&amp;quot; of the system (the features), but if they get involved in the innards by looking at logging, metrics, pair-programming and others, &lt;strong&gt;they can understand how the system works better&lt;/strong&gt;. This will help them be more effective on the analytical side of work, allowing them to be more effective at quality recommendations such as &amp;quot;We should write a test for this scenario&amp;quot; and &amp;quot;What should happen if this fails?&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This helps QA distinguish their role from:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;business analysts&lt;/strong&gt;, whose job is to develop a deep understanding of the domain, but &lt;em&gt;not necessarily&lt;/em&gt; how the system works on a technical level&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;product owners&lt;/strong&gt; who understand the customers, and how the system can help them&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;...when analysing work right at the start of the value chain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This will further help improve quality and increase capacity by reducing the chance of waste earlier in the pipeline.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;strong&gt;Things to do&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;&lt;strong&gt;Metrics&lt;/strong&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Metrics give you an overall view of how your system performs in response to requests. When done well, they help you understand how the system works better and can give you warning signs of incoming problems.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the one gap I&#39;ve noticed with many QA teams I&#39;ve worked with; they are very focused on how a feature behaves but not how it performs. Slow performance is annoying for users and tends to result in more errors because of timeouts and resource contention. Beyond performance, error rates when calling APIs help you understand areas of your system where you need to add more resiliency.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;strong&gt;Logs&lt;/strong&gt; / &lt;strong&gt;Tracing&lt;/strong&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Metrics give you an overview of the system, whereas logs &amp;amp; tracing show specific events. Analysing them can help you identify concrete areas where the system hasn&#39;t behaved as expected, common failure patterns, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The QA can then work with the developers to prioritise work to fix systemic issues that could otherwise get ignored, and end up pushing support costs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The team should pursue a “zero-defect culture”, where the logs are silent unless there is an actionable error. Too often, systems will log errors that are common failures that cannot be acted on, and they end up creating noise, masking actual quality issues.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you release code and it causes more errors, if you already have 100s, or thousands logged daily, you won&#39;t notice it, but your users might.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;strong&gt;Tests, pipelines&lt;/strong&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Flaky tests are a clear quality issue. Engineers will often lazily re-run pipelines, but that is ignoring the systemic issues. Flaky tests can be signals that your system isn&#39;t as resilient as you think. QAs can help diagnose these problems to support the developers in fixing them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;QAs should be very aware of the testing strategy of the system and offer statistics and guidance when the suite is not fit for purpose. Maybe the 20-minute functional test suite had some value a few years ago, but &lt;strong&gt;you know&lt;/strong&gt; it is stable, and we should remove some of them in favour of unit tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The speed and reliability of the pipeline &lt;strong&gt;are critical&lt;/strong&gt; and are prevalent forms of waste. It also has a heavy influence on your &lt;strong&gt;lead time&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;QAs and developers should feel ownership in making the pipeline as high quality as possible. It is akin to the factory worker in lean settings, ensuring it is as efficient as possible to reduce waste when manufacturing.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Automating other quality checks&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Some tests are part of the development process, which, again, tend to show you that the feature works in given conditions, and other lower-level tests like unit tests. However, there are numerous different kinds of tests that QAs can introduce to the system to help ensure quality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With their expert knowledge of the system&#39;s constraints, how it works, and what it needs to do, they can use their knowledge to tighten the feedback loop on the system&#39;s quality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other tests/checks QAs can introduce:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Performance (both backend and frontend)&lt;/li&gt;&#xA;&lt;li&gt;Accessibility&lt;/li&gt;&#xA;&lt;li&gt;Real user monitoring (RUM)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;&lt;strong&gt;Trends with bugs, support&lt;/strong&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;QAs should be involved with every support ticket and work with the rest of the team to determine what changes need to be made so the support never arrives on the development team&#39;s radar again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Visibility on common support issues, bugs and so on will help you identify the quality hot spots in your system, to help you prioritise proper fixes to reduce the waste surrounding these activities.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Support tickets are a result of a quality failure. Of course, it has to be expected mistakes will be made; no system is perfect, and we&#39;ll never have perfect knowledge, but that shouldn&#39;t be used as an excuse not to strive for perfection.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Support issues often form before a line of code is written:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Insufficient&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;domain knowledge&lt;/li&gt;&#xA;&lt;li&gt;customer knowledge&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Not understanding the &amp;quot;real&amp;quot; problem to solve&lt;/li&gt;&#xA;&lt;li&gt;Not thinking enough about non-happy path scenarios.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If everyone is on the ball, though and shifting left, they can be entirely avoided, but issues can also occur during the software being written and released.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Insufficient test automation around unexpected areas&lt;/li&gt;&#xA;&lt;li&gt;Incorrect test strategy (e.g. loads of unit tests, no integration tests -  &lt;a href=&#34;https://twitter.com/timbray/status/822470746773409794&#34;&gt;meme&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;Bad modelling allowing invalid domain states&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This &lt;em&gt;can&lt;/em&gt; be a touchy subject for some QAs as it can be perceived as making their role redundant. But I have seen first-hand how the good QAs who understand their role as &amp;quot;helping to ensure quality&amp;quot; and not &amp;quot;manual tester&amp;quot;, can embrace this change and make their role not only more useful to the team, but also more fulfilling for themselves.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The post&#39;s title frames this as a QA issue, but quality is a team-wide issue in practice. Teams that write rubbish, ill-thought software and throw it over the wall to a QA department are doomed to create bad products with lots of waste issues.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you are a team concerned with its capacity to do meaningful work, you need to be concerned with quality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Poor quality introduces waste, which is a drag on your capacity. Productivity killers include bugs, support requests, noisy error logs, and slow and flaky pipelines. The further &amp;quot;right&amp;quot; these issues are, the more significant their impact and the costlier they are to fix.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst I have written some specific things you can do, to truly be effective at this, you need to wear a lean hat, practice &lt;a href=&#34;https://en.wikipedia.org/wiki/Kaizen&#34;&gt;Kaizen&lt;/a&gt; and think about quality across the whole value chain of your work, which will always be context specific.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If something feels harder to do than it should, or you are frustrated at how you feel like you are working hard but not having the impact you&#39;d hoped for, &lt;strong&gt;listen to that signal, and look for waste&lt;/strong&gt;.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>HTMX is the Future</title>
      <link>https://quii.dev/HTMX_is_the_Future</link>
      <description>&lt;h2&gt;The current state of web application development&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;User expectations of the web are now that you have this super-smooth no-reload experience. Unfortunately, it&#39;s an expectation that is usually delivered with single-page applications (SPAs) that rely on libraries and frameworks like React and Angular, which are very specialised tools that can be complicated to work with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A new approach is to put the ability to deliver this UX back into the hands of engineers that built websites before the SPA-craze, leveraging their existing toolsets and knowledge, and HTMX is the best example I&#39;ve used so far.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The costs of SPA&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;SPAs have allowed engineers to create some great web applications, but they come with a cost:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Hugely increased complexity both in terms of architecture and developer experience. You have to spend considerable time learning about frameworks.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Tooling is an ever-shifting landscape in terms of building and packaging code.&lt;/li&gt;&#xA;&lt;li&gt;Managing state on both the client and server&lt;/li&gt;&#xA;&lt;li&gt;Frameworks, on top of libraries, on top of other libraries, on top of polyfills. &lt;a href=&#34;https://react.dev&#34;&gt;React even recommend using a framework on top of their tech&lt;/a&gt;:&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;React is a library. It lets you put components together, but it doesn’t prescribe how to do routing and data fetching. To build an entire app with React, we recommend a full-stack React framework.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;By their nature, a fat client requires the client to execute a lot of JavaScript. If you have modern hardware, this is fine, but these applications will be unusable &amp;amp; slow for those on older hardware or in locations with slow and unreliable internet connections.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It is very easy to make an SPA incorrectly, where you need to use the right approach with hooks to avoid ending up with abysmal client-side performance.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Some SPA implementations of SPA throw away progressive enhancement (a notable and noble exception is &lt;a href=&#34;https://remix.run&#34;&gt;Remix&lt;/a&gt;). Therefore, you &lt;em&gt;must&lt;/em&gt; have JavaScript turned on for most SPAs.&lt;/li&gt;&#xA;&lt;li&gt;If you wish to use something other than JavaScript or TypeScript, you must traverse the treacherous road of transpilation.&lt;/li&gt;&#xA;&lt;li&gt;It has created backend and frontend silos in many companies, carrying high coordination costs.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Before SPAs, you&#39;d choose your preferred language and deliver HTML to a user&#39;s browser in response to HTTP requests. This is &lt;em&gt;fine&lt;/em&gt;, but it offers little interactivity and, in some cases, could make an annoying-to-use UI, especially regarding having the page fully reload on every interaction. To get around this, you&#39;d typically sprinkle varying amounts of JS to grease the UX wheels.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst this approach can feel old-fashioned to some, this approach is what inspired the &lt;a href=&#34;http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm&#34;&gt;original paper of &lt;strong&gt;REST&lt;/strong&gt;&lt;/a&gt;, especially concerning &lt;strong&gt;hypermedia&lt;/strong&gt;. The hypermedia approach of building websites led to the world-wide-web being an incredible success.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Hypermedia?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The following is a response from a data API, not hypermedia.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;{&#xA;  &amp;quot;sort&amp;quot;: &amp;quot;12-34-56&amp;quot;,&#xA;  &amp;quot;number&amp;quot;: &amp;quot;87654321&amp;quot;,&#xA;  &amp;quot;balance&amp;quot;: &amp;quot;123.45&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To make this data useful in an SPA, the client code must understand the structure and decide what to render and what controls to make available.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;REST describes the use of hypermedia. Hypermedia is where your responses are not just raw data but are instead a payload describing the media (think HTML tags like &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;, headers, etc.) &lt;em&gt;and&lt;/em&gt; how to manipulate it (like &lt;code&gt;form&lt;/code&gt;, &lt;code&gt;input&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A server returning HTML describing a bank account, with some form of controls to work with the resource, is an example of hypermedia. The server is now responsible for deciding how to render the data (with the slight caveat of CSS) and &lt;em&gt;what&lt;/em&gt; controls should be displayed.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;dl&amp;gt;&#xA;  &amp;lt;dt&amp;gt;Sort&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;12-34-56&amp;lt;/dd&amp;gt;&#xA;  &amp;lt;dt&amp;gt;Number&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;87654321&amp;lt;/dd&amp;gt;&#xA;  &amp;lt;dt&amp;gt;Balance&amp;lt;/dt&amp;gt;&amp;lt;dd&amp;gt;£123.45&amp;lt;/dd&amp;gt;&#xA;&amp;lt;/dl&amp;gt;&#xA;&amp;lt;form method=&amp;quot;POST&amp;quot; action=&amp;quot;/transfer-funds&amp;quot;&amp;gt;&#xA;  &amp;lt;label&amp;gt;Amount &amp;lt;input type=&amp;quot;text&amp;quot; /&amp;gt;&amp;lt;/label&amp;gt;&#xA;  &amp;lt;!-- etc --&amp;gt;&#xA;  &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Do transfer&amp;quot; /&amp;gt;&#xA;&amp;lt;/form&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The approach means you have one universal client, the web browser; it understands how to display the hypermedia responses and lets the user work with the &amp;quot;controls&amp;quot; to do whatever they need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://changelog.com/gotime/266&#34;&gt;Carson Gross on The Go Time podcast&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;...when browsers first came out, this idea of one universal network client that could talk to any application over this crazy hypermedia technology was really, really novel. And it still is.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you told someone in 1980, “You know what - you’re gonna be using the same piece of software to access your news, your bank, your calendar, this stuff called email, and all this stuff”, they would have looked at you cross-eyed, they wouldn&#39;t know what you were talking about, unless they happened to be in one of the small research groups that was looking into this sort of stuff.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Before the World Wide Web, before web browsers, the prevailing patterns of apps were bespoke, and often &amp;quot;thick&amp;quot;, clients.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst ostensibly, people building SPAs talk about using &amp;quot;RESTful&amp;quot; APIs to provide data exchange to their client-side code, the approach is not RESTful in the purist sense because it does not use hypermedia.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of one universal client, &lt;em&gt;scores of developers create bespoke clients&lt;/em&gt;, which have to understand the raw data they fetch from web servers and then render controls according to the data. With this approach, the browser is more of a JavaScript, HTML and CSS runtime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By definition, a fatter client will carry more effort and cost than a thin one. However, the &amp;quot;original&amp;quot; hypermedia approach arguably is not good enough for all of today&#39;s needs; the controls that the browser can work with and the way it requires a full page refresh to use them mean the user experience isn&#39;t good enough for many types of web-app we need to make.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;HTMX and hypermedia&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Unlike SPAs, HTMX &lt;strong&gt;doesn&#39;t throw away the architectural approach of REST&lt;/strong&gt;; it &lt;em&gt;augments the browser&lt;/em&gt;, &lt;strong&gt;improving its hypermedia capabilities&lt;/strong&gt; and making it simpler to deliver a rich client experience without having to write much JavaScript if any at all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can use &lt;strong&gt;whatever programming language you like&lt;/strong&gt; to deliver HTML, just like we used to. This means you can use battle-tested, mature tooling, using a &amp;quot;true RESTful&amp;quot; approach, resulting in a far more straightforward development approach with less accidental complexity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;HTMX allows you to design pages that fetch &lt;strong&gt;fragments of HTML&lt;/strong&gt; from your server to update the user&#39;s page as needed without the annoying full-page load refresh.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&#39;ll now see this in practice with the classic TODO-list application.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Clojure HTMX TODO&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;First-of-all, please don&#39;t get overly concerned with this being written in Clojure. I did it in Clojure for fun, but the beauty of this approach is that you can use whatever language you like, so long as it responds to HTTP requests with hypermedia.&lt;/p&gt;&#xA;&#xA;&lt;video autoplay loop muted playsinline controls&gt;&#xA;  &lt;source src=&#34;static/videos/htmx/1.webm&#34; type=&#34;video/webm&#34; /&gt;&#xA;  &lt;source src=&#34;static/videos/htmx/1.mp4&#34; type=&#34;video/mp4&#34; /&gt;&#xA;  &lt;p&gt;&#xA;    Your browser doesn&#39;t support HTML video. Here is a&#xA;    &lt;a href=&#34;static/videos/htmx/1.mp4&#34;&gt;link to the video&lt;/a&gt; instead.&#xA;  &lt;/p&gt;&#xA;&lt;/video&gt;&#xA;&#xA;&lt;p&gt;Nothing special here, but it &lt;strong&gt;does feel like a SPA&lt;/strong&gt;. There are no full-page reloads; it&#39;s buttery smooth, just like all the other SPA demos you would&#39;ve seen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The difference here is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I did not write any JavaScript.&lt;/li&gt;&#xA;&lt;li&gt;I also didn&#39;t cheat by transpiling Clojure into JavaScript. (see &lt;a href=&#34;https://clojurescript.org&#34;&gt;ClojureScript&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I made a web server that responds to HTTP requests with hypermedia.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;HTMX adds the ability to define &lt;strong&gt;richer hypermedia&lt;/strong&gt; by letting you annotate &lt;em&gt;any HTML element&lt;/em&gt; to ask the browser to make HTTP requests to fetch fragments of HTML to put on the page.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The edit control&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The most exciting and impressive part of this demo is the edit action. The way an input box instantly appears for you to edit and then quickly update it again &lt;em&gt;feels&lt;/em&gt; like it would require either a lot of vanilla JS writing or a React-esque approach to achieve, but what you&#39;ll see is it&#39;s absurdly simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s start by looking at the markup for a TODO item. I have clipped the non-edit markup for clarity.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;li hx-target=&amp;quot;closest li&amp;quot;&amp;gt;&#xA;  &amp;lt;form action=&amp;quot;/todos/2a5e549c-c07e-4ed5-b7d4-731318987e05&amp;quot; &#xA;      method=&amp;quot;GET&amp;quot;&amp;gt;&#xA;      &amp;lt;button &#xA;        hx-get=&amp;quot;/todos/2a5e549c-c07e-4ed5-b7d4-731318987e05&amp;quot; &#xA;        hx-swap=&amp;quot;outerHTML&amp;quot;&amp;gt;&#xA;        📝&amp;lt;/button&amp;gt;&#xA;  &amp;lt;/form&amp;gt;&#xA;&amp;lt;/li&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;It maybe looks a lot, but the main things to focus on for understanding how the edit functionality works:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;On the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;, an attribute &lt;code&gt;hx-target&lt;/code&gt; tells the browser, &amp;quot;When you get a fragment to render, this is the element I want you to replace&amp;quot;. The children inherit this attribute, so for any HTMX actions inside this &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;, the &lt;code&gt;HTML&lt;/code&gt; returned will replace the contents of the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;hx-get&lt;/code&gt; on the edit button means when you click it, &lt;code&gt;HTMX&lt;/code&gt; will tell the browser to do an &lt;code&gt;HTTP GET&lt;/code&gt; to the &lt;code&gt;URL&lt;/code&gt; and fetch some new markup to render to the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; in place of what&#39;s there.&lt;/li&gt;&#xA;&lt;li&gt;The form is not essential for the example, but it allows us to support the functionality for non-JavaScript users, which will be covered later.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;When you start working with HTMX, an easy way to understand what&#39;s going on is to look at the network in the browser&#39;s developer tools.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;picture&gt;&#xA;  &lt;source type=&#34;image/webp&#34; srcset=&#34;static/videos/htmx/devtools.webp&#34; width=&#34;769&#34; height=&#34;286&#34; alt=&#34;a picture of the chrome developer tab, showing the browser fetching a resource&#34;&gt;&#xA;  &lt;img src=&#34;https://i.imgur.com/lnobOm5.png&#34; width=&#34;769&#34; height=&#34;286&#34; alt=&#34;a picture of the chrome developer tab, showing the browser fetching a resource&#34;&gt;&#xA;&lt;/picture&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a user clicks the edit button, the browser does an &lt;code&gt;HTTP GET&lt;/code&gt; to the &lt;em&gt;specific todo resource&lt;/em&gt;. The server returns a hypermedia response, which is a representation of that resource with some hypermedia controls.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;form action=&amp;quot;/todos/45850279-bf54-4e2e-a95c-c8c25866a744/edit&amp;quot;&#xA;      hx-patch=&amp;quot;/todos/45850279-bf54-4e2e-a95c-c8c25866a744&amp;quot; &#xA;      hx-swap=&amp;quot;outerHTML&amp;quot; method=&amp;quot;POST&amp;quot;&amp;gt;&#xA;  &amp;lt;input name=&amp;quot;done&amp;quot; type=&amp;quot;hidden&amp;quot; value=&amp;quot;false&amp;quot;/&amp;gt;&#xA;  &amp;lt;input name=&amp;quot;name&amp;quot; type=&amp;quot;text&amp;quot; value=&amp;quot;Learn Rust&amp;quot;/&amp;gt;&#xA;  &amp;lt;input type=&amp;quot;submit&amp;quot;/&amp;gt;&#xA;&amp;lt;/form&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;HTMX then takes that HTML and replaces whatever we defined as the &lt;code&gt;hx-target&lt;/code&gt;. So the user now sees these hypermedia controls for them to manipulate the resource, instead of the row pictured before.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&#39;ll notice the form has a &lt;code&gt;hx-patch&lt;/code&gt; attribute, which means when it is submitted, the browser will send a &lt;code&gt;PATCH&lt;/code&gt; with the data to update the resource. The server then responds with the updated item to render.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Embracing the web&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There&#39;s more to HTMX, but this is the crux of the approach, which is the same as the approach that most websites were made before SPAs became popular.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The user goes to a &lt;code&gt;URL&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The server returns hypermedia (HTML), which is content with controls.&lt;/li&gt;&#xA;&lt;li&gt;Browser renders hypermedia&lt;/li&gt;&#xA;&lt;li&gt;Users can use the controls to do work, which results in an HTTP request sent from the browser to the server.&lt;/li&gt;&#xA;&lt;li&gt;The server does business logic, and then returns new hypermedia for the user to work with&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All HTMX does, is make the browser &lt;strong&gt;better&lt;/strong&gt; at hypermedia by giving us more options regarding &lt;strong&gt;what can trigger an HTTP request&lt;/strong&gt; and &lt;strong&gt;allowing us to update a part of the page rather than a full page reload&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By embracing the hypermedia and not viewing the browser as merely a JavaScript runtime, we get a lot of simplicity benefits:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We can use any programming language on the server side.&lt;/li&gt;&#xA;&lt;li&gt;We don&#39;t need lots of libraries and other cruft to maintain what were basic benefits of web development.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Caching&lt;/li&gt;&#xA;&lt;li&gt;SEO-friendliness&lt;/li&gt;&#xA;&lt;li&gt;The back button working as you&#39;d expect&lt;/li&gt;&#xA;&lt;li&gt;etc.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;It is very easy to support users who do not wish to, or cannot use JavaScript&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This final point is crucial to me and to my current employer. I work for a company that works on products used worldwide, and our content and tools must be as usable by as many people as possible. It is unacceptable for us to exclude people through poor technical choices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why we adopt the approach of &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement&#34;&gt;&lt;strong&gt;progressive enhancement&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Progressive enhancement&lt;/strong&gt; is a design philosophy that provides a baseline of essential content and functionality to as many users as possible, while delivering the best possible experience only to users of the most modern browsers that can run all the required code.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;All the features in the TODO app (search, adding, editing, deleting, marking as complete) all work with JavaScript turned off. HTMX doesn&#39;t do this for &amp;quot;free&amp;quot;, it still requires engineering effort, but because of the approach, it is inherently simpler to achieve. It took me around an hour&#39;s effort and did not require significant changes.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;How it supports non-JavaScript&lt;/h3&gt;&#xA;&#xA;&lt;video autoplay loop muted playsinline&gt;&#xA;  &lt;source src=&#34;static/videos/htmx/2.webm&#34; type=&#34;video/webm&#34; /&gt;&#xA;  &lt;source src=&#34;static/videos/htmx/2.mp4&#34; type=&#34;video/mp4&#34; /&gt;&#xA;    &lt;p&gt;&#xA;    Your browser doesn&#39;t support HTML video. Here is a&#xA;    &lt;a href=&#34;static/videos/htmx/2.mp4&#34;&gt;link to the video&lt;/a&gt; instead.&#xA;  &lt;/p&gt;&#xA;&lt;/video&gt;&#xA;&#xA;&lt;p&gt;When the browser sends a request that was prompted by HTMX, it adds a header &lt;code&gt;HX-Request: true&lt;/code&gt; , which means on the server, we can send different responses accordingly, very much like &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation&#34;&gt;content negotiation&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The rule of thumb for a handler is roughly:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;parseAndValidateRequest()&#xA;myBusinessLogic()&#xA;&#xA;if request is htmx then&#xA;    return hypermedia fragment&#xA;else&#xA;    return a full page&#xA;end&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Here&#39;s a concrete example of the HTTP handler for dealing with a new TODO:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(defn handle-new-todo [get-todos, add-todo]&#xA;  (fn [req] (let [new-todo (-&amp;gt; req :params :todo-name)]&#xA;              (add-todo new-todo)&#xA;              (htmx-or-vanilla req&#xA;                               (view/todos-fragment (get-todos))&#xA;                               (redirect &amp;quot;/todos&amp;quot;)))))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The third line is our &amp;quot;business logic&amp;quot;, calling a function to add a new TODO to our list.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The fourth line is some code to determine what kind of request we&#39;re dealing with, and the subsequent lines either render a fragment to return or redirect to the page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So far, this seems a recurring theme when I&#39;ve been developing hypermedia applications with HTMX. By the very architectural nature, if you can support updating part of a page, return a fragment; otherwise, the browser &lt;em&gt;needs&lt;/em&gt; to do a full page reload, so either redirect or just return the entire HTML.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;HTML templating on the server is in an incredibly mature state. There are many options and excellent guides on how to structure and add automated tests for them. Importantly, they&#39;ll all offer some composition capabilities, so the effort to return a fragment or a whole page is extremely simple.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Why is it &lt;em&gt;The Future&lt;/em&gt; ?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Obviously, I cannot predict the future, but I do believe HTMX (or something like it) will become an increasingly popular approach for making web applications in the following years.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Recently, &lt;a href=&#34;https://github.blog/2023-04-12-github-accelerator-our-first-cohort-and-whats-next/&#34;&gt;HTMX was announced as one of 20 projects in the GitHub Accelerator&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It makes &amp;quot;the frontend&amp;quot; more accessible.&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Learning React is an industry in itself. It moves quickly and changes, and there are tons to learn. I sympathise with developers who &lt;em&gt;used&lt;/em&gt; to make fully-fledged applications being put off by modern frontend development and instead were happy to be pigeonholed into being a &amp;quot;backend&amp;quot; dev.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve made reasonably complex systems in React, and whilst some of it was pretty fun, &lt;strong&gt;the amount you have to learn to be effective is unreasonable for most applications&lt;/strong&gt;. React has its place, but it&#39;s overkill for many web applications.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The hypermedia approach with HTMX is not hard to grasp, especially if you have some REST fundamentals (which many &amp;quot;backend&amp;quot; devs should have). It opens up making rich websites to a broader group of people who don&#39;t want to learn how to use a framework and then keep up with its constantly shifting landscape.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Less churn&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Even after over 10 years of React being around, it still doesn&#39;t feel settled and mature. A few years ago, hooks were the new-fangled thing that everyone had to learn and re-write all their components with. In the last six months, my Twitter feed has been awash with debates and tutorials about this new-fangled &amp;quot;RSC&amp;quot; - react server components. Joy emoji.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Working with HTMX has allowed me to leverage things I learned 15-20 years ago &lt;strong&gt;that still work&lt;/strong&gt;, &lt;a href=&#34;https://quii.dev/How_my_website_works&#34;&gt;like my website&lt;/a&gt;. The approach is also well-understood and documented, and the best practices are independent of programming languages and frameworks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have made the example app in Go &lt;em&gt;and&lt;/em&gt; Clojure with no trouble at all, and I am a complete Clojure novice. Once you&#39;ve figured out the basic syntax of a language and learned how to respond to HTTP requests with hypermedia, you have enough to get going; and you can re-use the architectural and design best practices without having to learn a new approach over and over again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How much of your skills would be transferable from React if you had to work with Angular? Is it easy to switch from one react framework to another? How did you feel when class components became &amp;quot;bad&amp;quot;, and everyone wanted you to use hooks instead?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Cheaper&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&#39;s just less effort!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://hotwired.dev&#34;&gt;Hotwire&lt;/a&gt; is a library with similar goals to HTMX, driven by the Ruby on Rails world. DHH tweeted the following.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/dhh/status/1341758748717510659&#34;&gt;Hotwiring Rails expresses the desire to gift a lone full-stack developer all the tools they need to build the next Basecamp, GitHub, or Shopify. Not what a team of dozens or hundreds can do if they have millions in VC to buy  specialists. Renaissance tech for renaissance people.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That&#39;s why it&#39;s so depressing to hear the term &amp;quot;full stack&amp;quot; be used as a derogative. Or an impossible mission. That we HAVE to be a scattered band of frontend vs backend vs services vs whatever group of specialists to do cool shit. Absolutely fucking not.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Without the cognitive overload of understanding a vast framework from the SPA world and the inherent complexities of making a fat client, you can realistically create rich web applications with far fewer engineers.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;More resilient&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As described earlier, using the hypermedia approach, making a web application that works without JavaScript is relatively simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s also important to remember that the browser is an &lt;strong&gt;untrusted environment&lt;/strong&gt;, so when you build a SPA, you have to work extremely defensively. You have to implement lots of business logic client side; but because of the architecture, this same logic needs to be replicated on the server too.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For instance, let&#39;s say we wanted a rule saying you cannot edit a to-do if it is marked as done. In an SPA world, I&#39;d get raw JSON, and I&#39;d have to have business logic to determine whether to render the edit button on the client code somewhere. However, if we wanted to ensure a user couldn&#39;t circumvent this, I&#39;d have to have this same protection on the server. This sounds low-stakes and simple, but this complexity adds up, and the chance of misalignment increases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With a hypermedia approach, the browser is &amp;quot;dumb&amp;quot; and doesn&#39;t need to worry about this. As a developer, I can capture this rule in one place, the server.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Reduced coordination complexity&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The complexity of SPAs has created a shift into backend and frontend silos&lt;/strong&gt;, which carries a cost.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The typical backend/frontend team divide causes a lot of inefficiencies in terms of teamwork, with hand-offs and miscommunication, and &lt;strong&gt;makes getting stuff done harder&lt;/strong&gt;. Many people mistake individual efficiencies as the most critical metric and use that as justification for these silos. They see lots of PRs being merged, and lots of heat being generated, but ignoring the coordination costs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For example, let&#39;s assume you want to add a new piece of data to a page or add a new button. For many teams, that&#39;ll involve meetings between teams to discuss and agree on the new API, creating fakes for the frontend team to use and finally coordinating releases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the hypermedia approach, you &lt;strong&gt;don&#39;t have this complexity at all&lt;/strong&gt;. If you wish to add a button to the page, you can add it, and you don&#39;t need to coordinate efforts. You don&#39;t have to worry so much about API design. You are free to change the markup and content as you please.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Teams exchanging data via JSON can be &lt;strong&gt;extremely brittle&lt;/strong&gt; without care and always carries a coordination cost. Tools like consumer-driven contracts can help, but this is just &lt;em&gt;another&lt;/em&gt; tool, &lt;em&gt;another&lt;/em&gt; thing to understand and &lt;em&gt;another&lt;/em&gt; thing that goes wrong. The overheads, support and complexity of API versioning are &lt;strong&gt;inherently not an issue&lt;/strong&gt; with a hypermedia approach, you are free to change the markup as you please.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is not to say there is no room for specialisation. I&#39;ve worked on teams where the engineers built the web application &amp;quot;end to end&amp;quot;, but we had people who were experts on semantic, accessible markup who helped us make sure the work we did was of good quality. It is incredibly freeing not to have to negotiate APIs and hand off work to one another to build a website.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;More options&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Rendering HTML on the server is a very well-trodden road. Many battle-tested and mature tools and libraries are available to generate HTML from the server in every mainstream programming language and most of the more niche ones.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I encourage developers looking to reduce the costs and complexities of web application development to check out HTMX. If you&#39;ve been reluctant to build websites due to the fair assessment that front-end development is difficult, HTMX can be a great option.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;m not trying to claim that SPAs are now redundant; there will still be a real need for them when you need very sophisticated and fast interactions where a roundtrip to the server to get some markup won&#39;t be good enough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://quii.dev/The_Web_I_Want&#34;&gt;In 2018 I asserted that a considerable number of web applications could be written with a far simpler technological approach&lt;/a&gt; than SPAs. Now with the likes of HTMX, this assertion carries even more weight. The frontend landscape is dominated by waiting for a new framework to relieve the problems of the previous framework you happened to be using. The SPA approach is &lt;strong&gt;inherently more complicated than a hypermedia approach&lt;/strong&gt;, and piling on more tech might not be the answer, give hypermedia a go instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Check out some of the links below to learn more.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Further reading and listening&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The author of HTMX has written an excellent, &lt;a href=&#34;https://hypermedia.systems&#34;&gt;free book, explaining hypermedia&lt;/a&gt;. It&#39;s an easy read and will challenge your beliefs on how to build web applications. If you&#39;ve only ever created SPAs, this is an essential read.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://htmx.org&#34;&gt;HTMX&lt;/a&gt;. The examples section, in particular, is very good in showing you what&#39;s possible. The essays are also great.&lt;/li&gt;&#xA;&lt;li&gt;I was lucky enough to be invited onto &lt;a href=&#34;https://changelog.com/gotime/266&#34;&gt;The GoTime podcast with the creator of HTMX, Carson Gross to discuss it&lt;/a&gt;! Even though it&#39;s a Go podcast, the majority of the conversation was about the hypermedia approach.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/todo&#34;&gt;The Go version&lt;/a&gt; was my first adventure with HTMX, creating the same todo list app described in this post&lt;/li&gt;&#xA;&lt;li&gt;I worked on &lt;a href=&#34;https://github.com/ndchorley/todo&#34;&gt;The Clojure version&lt;/a&gt; with my colleague, Nicky&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://world.hey.com/dhh/the-time-is-right-for-hotwire-ecdb9b33&#34;&gt;DHH on Hotwire&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement&#34;&gt;Progressive enhancement&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Five years ago, I wrote &lt;a href=&#34;https://quii.dev/The_Web_I_Want&#34;&gt;The Web I Want&lt;/a&gt;, where I bemoaned the spiralling costs of SPAs. It was originally prompted by watching my partner&#39;s 2-year-old ChromeBook grind to a halt on a popular website that really could&#39;ve been static HTML. In the article, I discussed how I wished more of the web stuck to the basic hypermedia approach, rendering HTML on the server and using progressive enhancement to improve the experience. Reading back on this has made me very relieved the likes of HTMX have arrived.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 05 May 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>How to set a WIP limit</title>
      <link>https://quii.dev/How_to_set_a_WIP_limit</link>
      <description>&lt;p&gt;A colleague of mine is venturing into the magical world of Kanban, and one of the essential parts of Kanban is setting a &amp;quot;work-in-progress (WIP) limit&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A WIP limit dictates the number of items of work you can have in progress at a time. It dictates your maximum work capacity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/eOOQlvK.png&#34; alt=&#34;Example of WIP&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this example, the team can only have 2 items at play at a time. Even if you have a &amp;quot;spare dev&amp;quot;, she cannot start a new piece of work until one of the items in progress moves to Done.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&#39;re misinformed if you&#39;re not setting WIP limits and claiming to be doing Kanban.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what should your WIP limit be?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The Goal&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Goal_(novel)&#34;&gt;The Goal&lt;/a&gt;&lt;/em&gt; (highly recommended reading), describes a poorly performing manufacturing part. Imagine an assembly line, where parts of items are assembled from raw materials, which then get passed down to the next part of the line to be further assembled.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It could look like this:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Steel -&amp;gt; Bonnet -&amp;gt; Car&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Other parts of the plant will deal with building wheels, seats, fuzzy dice, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The performance of these parts of the plant is tightly micromanaged and appraised based on their output, e.g, how many bonnets can we produce per day?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most of the units could describe how they were performing well, yet the overall output of the plant was expensive and slow, constantly missing targets, and the profits were tumbling.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you look at the plant, you could see piles of inventory, waiting to be converted into real things that could actually be sold. The plant was &lt;em&gt;producing lots of stuff&lt;/em&gt; but not delivering real value to customers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The moment you buy some raw materials and start converting it into something you intend to sell sell, you&#39;ve taken liquid cash and turned it into inventory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Inventory is waste&lt;/strong&gt; until it delivers value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where the plant&#39;s management had lost sight of &lt;em&gt;The Goal&lt;/em&gt;. There&#39;s no point efficiently producing thousands of bonnets if they&#39;re not for the right car, or there are other bottlenecks in the plant for making wheels or whatever. The bonnets are dead weight, waste.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what if instead of worrying about local efficiencies, you started focusing on the actual company goal? What if you said you&#39;d only produce the number of bonnets you needed for a particular day, or better still &lt;strong&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Lean_manufacturing&#34;&gt;just-in-time&lt;/a&gt;&lt;/strong&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Surely this is terrible?! Our bonnet-making machine is just sitting idle! Remember, there&#39;s no point churning out tons of inventory if there&#39;s no immediate need for them. It&#39;s actively harmful, you&#39;re making more illiquid assets that need storage, insurance, security, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So how do you make more money? You must &lt;strong&gt;identify the bottlenecks, and improve them&lt;/strong&gt;. Only once you&#39;ve improved the capacity of your bottlenecks, can you increase the output of the other silos; and only if market demand dictates it wants more of your product, &lt;em&gt;the market&lt;/em&gt; is also a bottleneck.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One of the main messages of &lt;em&gt;The Goal&lt;/em&gt; is this. There&#39;s little point worrying about local efficiencies, it can actually make things worse sometimes! Only &lt;em&gt;The Goal&lt;/em&gt; is important; you need to look at the system as a whole and identify where best to improve.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Any improvements made anywhere besides the bottleneck are an illusion.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;~~Goldratt&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lean is all about making work &lt;em&gt;smooth&lt;/em&gt;, with &lt;em&gt;flow&lt;/em&gt;, minimal bottlenecks and reduced waste.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;In software&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Setting a WIP limit puts a hard constraint on what work your teams can do at once.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You might be asking yourself&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Seriously Chris? So if a developer is working on a ticket, but she can&#39;t finish it because deployments are blocked because another team&#39;s API is down, she has to sit there idle?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;As a manager, your job is not to ensure everyone looks busy. Your job is to fulfil &lt;em&gt;The Goal&lt;/em&gt;. &lt;strong&gt;Every time you park a ticket and pick up a new one, you choose to avoid dealing with a bottleneck&lt;/strong&gt;. &lt;u&gt;This bottleneck will keep harming your team and the company and slow its progress&lt;/u&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People love talking about breaking down silos in meetings; this is what should drive it. What if your engineer climbed out of the artificial play den you constructed and helped the other team relieve the bottleneck? Setting WIP limits give you &lt;strong&gt;clear indications as to what your bottlenecks are&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So much of &amp;quot;the DevOps movement&amp;quot; (which has its roots in lean manufacturing) is centred around automation, shift-left and breaking down silos. By making it, so a team owns not only the writing of the code but also deploying, testing and running it, you increase flow and reduce inventory.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Phoenix Project writes about how not adopting this approach is harmful. The company invested millions of dollars in the project, writing code for years. Then it was thrown over from the development team to the operations team to release to the customers. The execution was catastrophic, but the subtler point was that the company had piled up millions of dollars worth of inventory over many years without delivering any value.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Inventory?&lt;/h3&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/WoodyZuill/status/1609023035377586177&#34;&gt;Inventory: Something &amp;quot;paid for&amp;quot; not yet put to use (delivering value). If we write something in a backlog, write code, do testing, think about the thing, or do anything, it is something we have paid for. If we have not yet received value for it - it&#39;s inventory&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;~~ Woody Zuill&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you start writing code, it is inventory until it delivers value. It is something that costs to write, maintain, test, etc. When teams have piles of PRs waiting for approval, all work is invested in but not delivering value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;u&gt;It&#39;s inventory&lt;/u&gt;. What&#39;s worse is in software, we typically don&#39;t &lt;em&gt;really&lt;/em&gt; know if our work is valuable &lt;em&gt;until&lt;/em&gt; it is in the user&#39;s hands, and we want to collect feedback loops so that we can improve it to extract more value from the work. The longer your work sits as inventory, the longer you delay that crucial feedback loop.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your team views work as &amp;quot;done&amp;quot; when a PR is raised, you are not looking at the overall system, just like the plant in The Goal. The back-and-forth review, perhaps manual testing, and all the steps between that and it being used by a customer are all bottlenecks you&#39;re choosing to ignore.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Monitoring pull requests raised/closed is akin to measuring how many bonnets you produce.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Mature teams that achieve a good flow of value will review code quickly (ideally on-demand with mobbing or pair-programming), automate all tests and have a reliable deployment pipeline. Hence, inventory never piles up, and they can deliver value quickly.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Definition of done&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is why it&#39;s essential to clearly understand what &amp;quot;done&amp;quot; means, and a story shouldn&#39;t move into the &amp;quot;done&amp;quot; column of a Kanban board until it meets your done criteria.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These criteria should include &lt;strong&gt;deployed to production, used by real people and generating value&lt;/strong&gt;. It should include other things, which mean it&#39;s done to sound quality, such as testing, observability, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When something is done, it should not require any more &lt;em&gt;planned&lt;/em&gt; work from the team. &lt;strong&gt;Otherwise, it&#39;s still a work in progress&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;But Chris, the marketing team want us to hide it behind a feature flag for a few months before they get a campaign ready.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&#39;s still WIP! It is still unvalidated ideas and work that is not delivering value. Why is marketing a bottleneck? What could you do as an organisation to be more nimble concerning marketing? &lt;u&gt;You&#39;re still thinking locally&lt;/u&gt;. &lt;strong&gt;Think about The Goal!&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Too often, software development organisations celebrate the amount of work they&#39;ve done; it may even be deployed to production, but if no one uses it, &lt;strong&gt;it&#39;s still inventory and waste&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Be honest about what &amp;quot;done&amp;quot; means&lt;/strong&gt;; don&#39;t be content with being an efficient bonnet-making silo within the plant. Thinking about &amp;quot;done&amp;quot; will make you answer some tough but essential questions about the way your organisation tries to deliver value.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;How to keep WIP low&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Reduce toil. A system that is simple to work on will have a smooth flow of work. Flaky tests and slow builds all contribute to work stalling.&lt;/li&gt;&#xA;&lt;li&gt;Automate all the things. You will always suffer from bottlenecks if you have to wait for someone to test something or do a security review manually. See: &lt;a href=&#34;https://en.wikipedia.org/wiki/Shift-left_testing&#34;&gt;&lt;strong&gt;&amp;quot;shift left&amp;quot;&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Reduce scope. Work in small, achievable steps. Think of ways to frequently deliver small amounts of value rather than &amp;quot;big bang&amp;quot;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Focus on the goal, and work as a team&lt;/strong&gt;. Encourage a culture within your team of helping each other keep WIP low. Once you finish a task, rather than starting a new one, help your colleagues finish their tasks too. If you find dependencies on other teams are causing bottlenecks, try to help them too.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The perils of high WIP&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There is a very real sense of chaos. Many plates are being spun, lots of context switching. Your team will work hard but feel inadequate regarding the actual value (The Goal) being delivered. This will hurt morale. Having high effort but low outcome/reward is commonly linked with burnout.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;A recent, sad tale&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve seen in the past year how a combination of socio-technical, and organisational issues have caused subtle, but very harmful bottlenecks for the team I&#39;ve managed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing this stuff is simple, but I won&#39;t pretend it&#39;s easy to solve! Nonetheless, you must try.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I needed to communicate these issues more effectively and get sufficient buy-in to deal with them appropriately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Capturing data sooner would&#39;ve helped build a more coherent case. When planning work, identify potential bottlenecks and find ways to measure them so you can find the problems quickly with concrete data.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;So what number should you set?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As with all things process and methodology, you should not cargo-cult and get lost in a particular implementation, but instead, understand why the practice is essential. This will allow you to tailor it to your specific context, and I hope this post has given you an understanding of what setting a WIP limit accomplishes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The specific number is insignificant; what&#39;s important is the flow of work and listening to the signals the limit provides you, mainly what your bottlenecks are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I&#39;m starting with a new team, my rule of thumb is roughly &lt;code&gt;(Number of devs / 2) + 1&lt;/code&gt;, and I take it from there.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If work is sitting in progress or parked for long periods, your &amp;quot;inventory&amp;quot; is high, and you likely have bottlenecks you&#39;re not addressing. Setting a WIP limit lets you &amp;quot;see&amp;quot; these bottlenecks more clearly. If you choose to ignore these bottlenecks, though, your team will suffer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If work goes from idea to done (and remember, actually done and delivering value) smoothly and quickly, you probably have your WIP limit at the right level.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 14 Jan 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>My job advert for 2023</title>
      <link>https://quii.dev/My_job_advert_for_2023</link>
      <description>&lt;p&gt;I&#39;m looking for a new software developer/engineering manager role, and this post will summarise me for potential employees.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This blog is a fair reflection on my general attitudes towards software development, what&#39;s important to me, what I feel works, and what doesn&#39;t!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My hope is someone will read this and think.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Chris&#39;s experience, values, and work methods align with what we need, and we should chat with him.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If I look like a good fit, &lt;a href=&#34;https://www.linkedin.com/in/chris-james-5ba74b15/&#34;&gt;contact me&lt;/a&gt; and dig into other posts here to see more of what makes me tick. If you wish to prepare for our interview, &lt;a href=&#34;https://quii.dev/Interview_questions_as_a_candidate&#34;&gt;I already have my questions written down for you&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The headlines&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Happy to be either an engineering manager or a developer within a team.&lt;/li&gt;&#xA;&lt;li&gt;I&#39;m happiest and probably most effective when I am coaching and pairing with engineers &amp;amp; teams.&lt;/li&gt;&#xA;&lt;li&gt;Around 17 years of professional software-engineering experience&lt;/li&gt;&#xA;&lt;li&gt;My most recent experience is with &lt;strong&gt;Go&lt;/strong&gt;, but I have shipped numerous production systems in &lt;strong&gt;Type/JavaScript&lt;/strong&gt;, &lt;strong&gt;Kotlin&lt;/strong&gt;, and &lt;strong&gt;Scala&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;I&#39;ve worked on various systems during my career, from client-side heavy, niche data exploration tools and backend APIs to websites serving hundreds of requests per second across the globe.&lt;/li&gt;&#xA;&lt;li&gt;I am the author of the popular resource &lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/&#34;&gt;Learn Go with Tests&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Stuff I like&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Trunk-based development&lt;/li&gt;&#xA;&lt;li&gt;TDD&lt;/li&gt;&#xA;&lt;li&gt;Continuous delivery (10 deploys per day, DORA metrics, that kind of vibe)&lt;/li&gt;&#xA;&lt;li&gt;Autonomy with responsibility. You build it; you run it.&lt;/li&gt;&#xA;&lt;li&gt;Kanban (not scrum)&lt;/li&gt;&#xA;&lt;li&gt;Iterative, lean development practices&lt;/li&gt;&#xA;&lt;li&gt;XP&lt;/li&gt;&#xA;&lt;li&gt;Stream-aligned teams (think Conway&#39;s Law and topics discussed in Team Topologies)&lt;/li&gt;&#xA;&lt;li&gt;Learning, coaching and mentoring. A curious and learning-focused engineering culture is very important to me. Every place I work I try to encourage and facilitate book clubs, katas, lightning talks, etc.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;My answers to the usual questions&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;What are you most proud of professionally?&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Writing &lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/&#34;&gt;Learn Go with Tests&lt;/a&gt; and seeing what a positive impact it&#39;s had on many engineers.&lt;/li&gt;&#xA;&lt;li&gt;My conference and meetup talks (&lt;a href=&#34;https://quii.dev/Speaking_at_GopherconUK&#34;&gt;Gophercon UK&lt;/a&gt;, &lt;a href=&#34;https://quii.dev/The_Tests_Talk&#34;&gt;London Gophers&lt;/a&gt;) and being invited to &lt;a href=&#34;https://changelog.com/gotime&#34;&gt;Go Time&lt;/a&gt; a few times&lt;/li&gt;&#xA;&lt;li&gt;Participating in several junior engineers&#39; journeys, helping and guiding them to well-deserved promotions and pay raises. The thing I am probably most proud of is hiring a group from &lt;a href=&#34;https://makers.tech&#34;&gt;Makers Academy&lt;/a&gt;, a coding boot-camp, and fostering a fun, curious and effective engineering team.&lt;/li&gt;&#xA;&lt;li&gt;Helping teams become more effective in their development and release practices, making work more straightforward, less stressful and more effective. We&#39;re a good fit if you have heard of DORA metrics.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;What are you looking for?&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I am happiest when I am in a team that is constantly growing. I love coaching, guiding, and learning from people smarter than me. I want an environment where engineers are humble and curious about software engineering. My dream role is to be a coach.&lt;/li&gt;&#xA;&lt;li&gt;Go, ideally, but I also like Kotlin and JavaScript (mostly). I enjoy programming, and if you&#39;re happy to accept additional ramp-up time for me to learn something new, I&#39;m more than excited to do that. Any Rust roles?&lt;/li&gt;&#xA;&lt;li&gt;A team of diverse backgrounds. I&#39;ve been lucky to work in teams over the past five years with people from various backgrounds, making me a better engineer and person.&lt;/li&gt;&#xA;&lt;li&gt;I love seeing metrics fly up that represent actual people using the software. Feeling a connection between the work to tangible outcomes is fantastic.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Can you complete these data structures and algorithms / cracking the coding interview / leetcode exercises?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&#39;d rather not. I last thought about bubble sort et al. around 2002.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve designed a number of interview processes, securing some excellent colleagues. They&#39;ve always involved a small but practical homework that has helped us understand the quality of the code they write in a team setting (think testing, coupling/cohesion, separation of concerns, etc.), rather than whether they can invert a binary tree or not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii&#34;&gt;Look at my GitHub&lt;/a&gt; if you need clarification on whether I can write code, or &lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/&#34;&gt;look at Learn Go with Tests&lt;/a&gt; as I clearly explain my thought process.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Values and principles&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Quality and delivery speed are correlated, not traded-off&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Dave Farley&#39;s book &lt;a href=&#34;https://www.amazon.co.uk/Modern-Software-Engineering-Really-Better/dp/0137314914&#34;&gt;Modern Software Engineering&lt;/a&gt; encompasses my views of what practical engineering looks like. If you&#39;ve read that book and it resonates, I&#39;d love to work with you. One topic he covers is that teams often take shortcuts and technical debt to go faster, but when we bring evidence to the picture, we find it&#39;s a false economy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The State of DevOps reports debunk the idea we trade speed and quality off; they are &lt;strong&gt;correlated&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we&#39;re honest, we all know this to be true. How many times have you opened a garbage codebase and wasted days or weeks trying to make a minor change?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way to go fast is to write high-quality, &lt;em&gt;small&lt;/em&gt; increments, get feedback, change direction, and repeat. See also: &lt;a href=&#34;https://quii.dev/How_to_go_fast&#34;&gt;How to go fast&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Empowered teams&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&#39;m not too fond of the idea of story robots. Programmers on an assembly line picking up tickets from JIRA, mindlessly doing them and throwing them into &amp;quot;done&amp;quot;. Never questioning the work and never working with real users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have no interest in leads, seniors or BAs sitting in ivory towers writing tickets and throwing them over the wall to some poor, demotivated programmers who are judged by how many tickets they complete or how many PRs they approve per week.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I want my teams to be given a real user problem and for them to work together to figure out how to solve it. They should focus on actual business outcomes, not &amp;quot;velocity&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Velocity is an abstract concept; if a team has a &amp;quot;good&amp;quot; velocity, it doesn&#39;t mean they&#39;re solving real problems. High velocity is only useful if you&#39;re going in the right direction.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Work-life balance&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I feel very blessed to have a profession that I enjoy, but that doesn&#39;t mean I will sacrifice my personal life for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The need for long hours and heroism often ruin work-life balance. Heroism is a symptom and a bandaid for organisations that fail to manage work correctly, execute poorly on a technical level and not having the courage to say &amp;quot;no&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;(Another good sign of compatibility is if you know what I mean by &amp;quot;That looks like a Brent&amp;quot;, referencing The Phoenix Project)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Occasional acts of heroism are sometimes necessary, I&#39;m never jobsworth about my role and only work strict hours, and it can feel good to save the day; but it should be the exception, not the norm.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I run teams, I optimise the way we work so that we try and do things properly and not be woken up at 3 am, and if work is taking longer than people hoped, we deal with it, find ways to improve, cut scope, etc., but not demand engineers work late nights which for the most part, tends to make things worse.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your job description includes phrases like a &lt;strong&gt;fast-paced environment&lt;/strong&gt; or &lt;strong&gt;working well under pressure,&lt;/strong&gt; that gives me some red flags.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Honesty, with respect and empathy&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Honesty is extremely important, and when I build teams, I do my best to try and build a safe environment for people to express their views so we can grow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;quot;Constructive&amp;quot; feedback is an act of kindness &lt;strong&gt;if it is done kindly&lt;/strong&gt;. Honesty does not have to come at the expense of respect and empathy.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Learning culture&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I love learning and improving my craft. By our industry&#39;s standards, I am very experienced, but I am still excited to challenge myself to improve and learn new things.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So many organisations bemoan the output of their engineering teams but are unwilling to do anything concrete to increase capacity beyond cracking whips. I want to work in organisations that invest in their teams to help them improve; things like 10% time are good examples of this.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It also should be happening on a day-to-day basis. Pair programming, mobbing, retrospectives, etc., are all important tools to help teams and people improve. A safe environment where people can be fearless to try things without fear of reprisal if something goes wrong is key to growth and innovation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This also relates to my first point: quality and speed are correlated, not traded off. The better we get at writing software, the more we understand the domain, the higher the quality of the systems we build and, therefore, the more value we can deliver. If this doesn&#39;t align with you, it will be difficult.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Other practicalities&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Remote?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Even though I am an introvert pretending to be an extrovert, I like going to the office and seeing people face to face. That said, depending on &lt;em&gt;where&lt;/em&gt; in London your office is, it might take a long time. Either way, it is very expensive (I live just outside London), so I prefer to go 1-2 times per week maximum. I can make occasional exceptions; for instance, if you&#39;re doing a week-long project inception, that&#39;s fine.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am open to being 100% remote, but so far, my one experience (during Covid) could have been more enjoyable. I feel I suffered from &amp;quot;Zoom fatigue&amp;quot;.  Maybe our environment did remote work wrong, though, and I appreciate lots of people swear by it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I also am okay with travelling abroad from time to time.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;When?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I prefer to start around March, but have some flexibility.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Salary?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Nice try. You tell me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PS, everyone has a &amp;quot;competitive salary&amp;quot;.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 02 Jan 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>2022</title>
      <link>https://quii.dev/2022</link>
      <description>&lt;p&gt;Work has been a mixture of a lot of highs and lows. My current place is quite chaotic; there have been leadership changes that bring in different ideas and expectations. Re-orgs often tend to be tough, where you find different people&#39;s values and ways of work clashing. Over this year, I&#39;ve had three different line managers, which has sometimes caused problems. These are all fairly normal growing pains, and in a lot of ways things have improved as the year has gone on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have learned that expectation management is an essential skill for an EM (engineering manager), it&#39;s not enough to assume people will trust you, and people need clarity as to why something is taking longer than they expect. Explaining why a complex system (both in terms of tech and the social side) is taking &amp;quot;longer than expected&amp;quot; has been difficult and stressful for me. Not something I&#39;ve enjoyed, and it has made me question my skills and motivations for being an EM.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I need to reflect on how I can explain these ideas better if I can protect my team better and, on a personal level, have a healthier work-life balance. On previous projects I leveraged &lt;a href=&#34;https://www.oreilly.com/library/view/agile-experience-design/9780132869249/part03lev1sec30.html&#34;&gt;&amp;quot;sliders&amp;quot;&lt;/a&gt; to get buy-in and clarity around the kinds of trade-offs teams need to make with work. I think it was a big error on my part not to use this tool and get blessing from senior management.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So there are a lot of things to stress about, but importantly, my team are delivering, and it all seems to be more-or-less coming together as the year finishes. Our part of a large and complex system is rolling out across Europe for thousands of customers. My team has been put under a lot of pressure, which I have tried to manage as best I can, not always successfully, but I hope they recognise their achievements. It&#39;s sometimes easy to get lost in the dozens of bits of work we need to do, which will seriously help the business in tangible ways.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;No matter how it all pans out, I&#39;m also extremely pleased and proud of how the team has grown over this year. We&#39;ve got &lt;strong&gt;much better&lt;/strong&gt; at writing software as a group. We&#39;ve learned many essential concepts in writing sound systems, particularly automated tests, TDD, contract testing, London vs Chicago, and many more. Our code-review sessions, mobbing and pairing, have brought up some fascinating ideas, precisely what I&#39;m looking for when trying to build teams. I&#39;m proud that members of my team have gone to other teams to help coach these modern engineering practices to good effect and have a wider impact to the engineering organisation. To top it all off, 2 on my team got well-deserved promotions; I&#39;m thrilled for them.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Open-source / community things&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Given how hectic work has been, it was surprising to look back and see I still found the time and inclination to write five new chapters for Learn Go with Tests this year.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/html-templates&#34;&gt;Templating&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/generics&#34;&gt;Generics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/revisiting-arrays-and-slices-with-generics&#34;&gt;Revisiting arrays and slices with generics&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/testing-fundamentals/intro-to-acceptance-tests&#34;&gt;Introduction to acceptance tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/testing-fundamentals/scaling-acceptance-tests&#34;&gt;Scaling acceptance tests&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I was also lucky enough to be invited for my 3rd episode of &lt;a href=&#34;https://changelog.com/gotime/258&#34;&gt;Go Time&lt;/a&gt;. In this episode, we discussed TDD with someone who is not a fan.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Goals for next year&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Not going to be too hard on me if I don&#39;t achieve these, but it&#39;s nice to think ahead.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Professional&lt;/h3&gt;&#xA;&#xA;&lt;h4&gt;Keep on top of Learn Go with tests.&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;It&#39;s cool and appreciated how many issues and PRs are raised, but I feel guilty about not addressing them quickly; this will be a constant struggle.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have a few new chapter ideas that would be nice to try out:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Living without mocks&lt;/li&gt;&#xA;&lt;li&gt;Nested testing&lt;/li&gt;&#xA;&lt;li&gt;Fuzzing&lt;/li&gt;&#xA;&lt;li&gt;Browser testing&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;Back to a simpler world with web development&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;I am thrilled that technologies like &lt;a href=&#34;https://htmx.org&#34;&gt;htmx&lt;/a&gt; and &lt;a href=&#34;https://hotwired.dev&#34;&gt;hotwire&lt;/a&gt; are gaining traction. &lt;a href=&#34;https://quii.dev/The_Web_I_Want&#34;&gt;I have long expressed how much I hate the proliferation of client-heavy SPAs&lt;/a&gt;, about how much complexity they bring to making simple websites.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With the likes of htmx, we can go back to a world of rendering HTML on the server, which is extremely simple and battle-tested; but still have a smooth client-side experience for the user. It also liberates from using Node on the server; if your &lt;code&gt;$FAVOURITE_LANGUAGE&lt;/code&gt; can respond to HTML requests, you can make great websites.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/todo&#34;&gt;I experimented with this&lt;/a&gt; during some time off, and many people were &lt;a href=&#34;https://twitter.com/quii/status/1598987894865113088&#34;&gt;engaging with it on Twitter.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I find time, I think I can write a lot of material around web development and Go using this way of working.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Speak at GopherCon US&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;I was lucky enough to speak at Gophercon UK a few years back. A while ago, I applied to talk at a few state-side conferences and didn&#39;t get a response. I want to try again, as it is a personal ambition to speak at a conference outside the UK that I&#39;m not quite willing to give up on just yet.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe the simpler web development approach would make a decent conference proposal.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Personal&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You can probably stop reading here; this is just for me :)&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;April this year, I weighed 107kg (I am 6&#39;2&amp;quot; tall), which was terrible. The pandemic and work led to a lot of inactivity and stress-eating, which is a bad combo. I went back to basics, tracking calories and exercising, and seven months later, I am 91.4kg! Very pleased with this progress; I fit into all my clothes again. I want to push on next year and get myself down to around 85kg.&lt;/li&gt;&#xA;&lt;li&gt;As part of the above, I got into &amp;quot;couch to 5k&amp;quot; and have since completed a few 5k runs. I am unfit still and relatively slow; it takes me 33 minutes. I want to try and push this to 30 minutes, but honestly, I have no idea if that is good/impossible. Either way, something to improve at.&lt;/li&gt;&#xA;&lt;li&gt;I waste so much money on computer games that are probably really good, but I don&#39;t have time—budgeting myself a max of 4 new games next year to force myself to at least make choices not to be so impulsive.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sun, 11 Dec 2022 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Speaking at GopherconUK</title>
      <link>https://quii.dev/Speaking_at_GopherconUK</link>
      <description>&lt;p&gt;For several years, I had an ambition to speak at some kind of Gopher conference event, especially to talk about testing, which is a subject that is so misunderstood. I&#39;ve been doing the whole testing thing for quite a long time now, and I still find lots to learn. So, I get irritated when developers of 2 years experience tell me, so full of confidence, that &amp;quot;no-one does TDD in the real world&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A few years ago, to work toward this goal, I set myself a shorter-term goal of &lt;a href=&#34;/The_Tests_Talk&#34;&gt;speaking at London Gophers&lt;/a&gt;. It went pretty well, I was proud of the talk and how it went. However, when I went on to apply at various call-for-papers for Gophercons around the world, well, I didn&#39;t get anywhere. My rational brain knows it was very competitive and was pretty natural to not get any responses at all, but I still took the failure a bit personally and gave up on the idea.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, I was pretty thrilled to get the opportunity to speak at &lt;a href=&#34;https://www.gophercon.co.uk&#34;&gt;GopherconUK&lt;/a&gt; and even more excited that I roped &lt;a href=&#34;https://www.riyadattani.com&#34;&gt;Riya Dattani&lt;/a&gt; in to speaking with me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I won&#39;t go too much into the material, &lt;a href=&#34;https://www.youtube.com/watch?v=ZMWJCk_0WrY&#34;&gt;watch the video on YouTube&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But I will say it&#39;s a combination of many thoughts I&#39;ve had in general with testing, from reading things like &lt;a href=&#34;https://www.amazon.com/dp/0321601912?tag=contindelive-20&#34;&gt;Continuous Delivery&lt;/a&gt;, &lt;a href=&#34;http://www.growing-object-oriented-software.com&#34;&gt;GOOS&lt;/a&gt; and even everyone&#39;s favourite novel; &lt;a href=&#34;https://itrevolution.com/the-phoenix-project/&#34;&gt;The Phoenix Project&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Testing has a profound effect on your ability to ship software effectively, without toil, and it even has an influence on how your team works and how it solves problems. It&#39;s a far bigger subject than merely preventing bugs.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Reflections on the experience&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I definitely have a new-found respect for good conference speakers. It is &lt;em&gt;hard work&lt;/em&gt;. We worked really hard on it, for almost 2 months (not to mention the years of studying, experience and reflection beforehand!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first month was &amp;quot;just&amp;quot; making the slides, which was actually harder work than I thought it would be. Trying to come up with a talk that had to be around 40 minutes but still have a coherent narrative and flow is tough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We had a lot of support from friends and colleagues, which helped a ton.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the day, we were obviously nervous, but once we were on the stage it was honestly straightforward. It was like we had done it 100 times before because we had.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Tips&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Before committing to doing a talk at a conference, know that it will suck up your life for 6-8 weeks if you&#39;re going to do it properly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I remember saying to Riya:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I don&#39;t want us to not try hard enough and then use that as an excuse if we don&#39;t do well. Let&#39;s stick our necks out a bit, and take advantage of this opportunity and do a good job.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Other side-projects and things will probably need to be paused for a while. The effort on preparation will pay dividends, though. It&#39;s not that we did it perfectly, but it went as well as I hoped it would, and I enjoyed the experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;m not a prolific public speaker, I&#39;ve only done it a few times, so take the following with a pinch of salt. However, Lara Hogan has an excellent free book - &lt;a href=&#34;https://demystifying-public-speaking.com&#34;&gt;Demystifying Public Speaking&lt;/a&gt; which is definitely worth a look.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe there are naturally gifted speakers who can just wing some slides on the plane, for the rest of us though, this is what I&#39;d recommend.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Practicing effectively&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I committed to practicing my part of the talk at least 2 times a day. I wanted to avoid relying on presentation notes too much, and I wanted to be fluent at what I wished to communicate on every slide. Perhaps that&#39;s over the top, but it gave me confidence when I was on the stage.&lt;/li&gt;&#xA;&lt;li&gt;Practice &lt;strong&gt;out-loud&lt;/strong&gt;. Reading your slides is not practicing what you&#39;re going to do on the day.&lt;/li&gt;&#xA;&lt;li&gt;Practice your talk standing up. Your posture, breathing e.t.c. is just different compared to sitting, and you want it to be as close to the real thing as possible.&lt;/li&gt;&#xA;&lt;li&gt;Try mixing it up, so you practice each section effectively. For instance, practicing doing slides X to Y a few times over, rather than the whole thing.&lt;/li&gt;&#xA;&lt;li&gt;If you&#39;re inexperienced with public speaking, you might want to start by speaking with your colleagues first. At my previous and current job, we&#39;ve set up a &lt;a href=&#34;https://en.wikipedia.org/wiki/Lightning_talk&#34;&gt;lightning talks&lt;/a&gt; initiative where people regularly do short talks to the rest of the group to share knowledge and practice communicating effectively. With a healthy feedback culture, your team/company can get better at sharing ideas, and it can set you up for public speaking.&lt;/li&gt;&#xA;&lt;li&gt;Record yourself, and listen to it.&lt;/li&gt;&#xA;&lt;li&gt;Get feedback from your friends/colleagues early, don&#39;t be afraid to show something rough.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;Preparing the talk&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Start early. You&#39;ll never regret being over-prepared.&lt;/li&gt;&#xA;&lt;li&gt;Try to identify a central narrative first. Think about what the audience will specifically take away from the talk. Ask yourself what an engaged audience member would do when they get back to the office.&lt;/li&gt;&#xA;&lt;li&gt;Find time to keep researching for ideas and perspectives. Even though I had a pretty good idea of what I wanted us to convey, by reading some other books whilst writing the talk I learned some different ideas and incorporated them into the talk.&lt;/li&gt;&#xA;&lt;li&gt;People like stories and anecdotes, try to weave them in to your talk. I think Riya&#39;s experiences of how BDD helped her as a junior dev in particular were a different and interesting take on the material that I hadn&#39;t heard before.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;On the day&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Remind yourself that you&#39;ve done this 100 times before.&lt;/li&gt;&#xA;&lt;li&gt;Remind yourself that people &lt;em&gt;want&lt;/em&gt; to hear a good talk. You&#39;re not in high-school any more, people won&#39;t taunt you for messing up.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;It doesn&#39;t need to be perfect&lt;/strong&gt;, it doesn&#39;t matter if you briefly lose your way, or misspeak.&lt;/li&gt;&#xA;&lt;li&gt;Your talk won&#39;t be for everyone. Some people won&#39;t like it, and that&#39;s ok.&lt;/li&gt;&#xA;&lt;li&gt;You&#39;re going to get to talk about something you&#39;re passionate about to a captive audience, this is cool and a real privilege.&lt;/li&gt;&#xA;&lt;li&gt;Try to enjoy it, you&#39;ll probably find yourself nervous for the first few minutes, then you&#39;ll get into your rhythm, and it&#39;ll be over before you know it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 29 Nov 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Reduce WIP by practicing trunk-based development, rather than pull requests</title>
      <link>https://quii.dev/Reduce_WIP_by_practicing_trunk-based_development,_rather_than_pull_requests</link>
      <description>&lt;p&gt;Poorly managed work in progress (WIP) is a common cause for low performance in development teams. When you have a team juggling too much work, it engages in frequent, expensive context switching, which reduces quality and slows delivery. Your team is working hard, but not delivering.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The reduction in quality has a compounding effect on WIP as you will get unexpected bugs, re-work, and outages; which in itself causes more WIP. Unplanned work is poison for productivity and predictability.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Managing WIP involves looking at how work &lt;strong&gt;flows&lt;/strong&gt; through your system, trying to make it go quickly, smoothly and predictably. Identifying bottlenecks &amp;amp; constraints allows you to manage them more effectively and focus your efforts on improving them and making sure only the highest priority work goes to them. Any efforts to improve efficiency outside these constraints is waste because it’s the bottlenecks in your system that dictate pace. With a focus on quality you can reduce the amount of unplanned work which helps you manage WIP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is no one true way of working, the best method depends on your team and the context they’re in. Managing WIP, and having a smooth flow of work, is not a negotiation if you are serious about managing an effective team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pretend you are the lead of a 4-person development team. How your team approaches creating value obviously has a big impact on its ability to deliver it, yet many teams copy other team’s rigid models, rather than thinking about the context they are in and tailoring the process to it.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The open source, pull-request model&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is an often-cited, popular way for teams to work.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Each developer picks up a ticket/story/task&lt;/li&gt;&#xA;&lt;li&gt;Developer writes code on a branch. This allows them to work isolated, focused, and not affect other team members with their work which may not be completed.&lt;/li&gt;&#xA;&lt;li&gt;When the developer believes the work is finished, they raise a pull request. When another developer is free, they can take a look at the work and then initiate a feedback cycle with the person who raised the PR until it is of sufficient quality.&lt;/li&gt;&#xA;&lt;li&gt;The code gets merged and deployed to customers&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Often the reasons people adopt this model is it allows a degree of gatekeeping and socialising knowledge. It’s argued that it can help prevent mistakes from being shipped and maintain code quality.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;High WIP&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;For a team of 4 developers, having at least 4 tickets in play at a time &lt;em&gt;feels&lt;/em&gt; like high WIP. Chasing 100% “resource” allocation is not a desirable management goal because all systems need a level of slack to cope with unexpected work. If a team is running at full-capacity it is inflexible, and inflexible things tend to break under pressure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you raise a PR and none of your colleagues are free, you may be tempted to pick up another ticket. The WIP of the team has now increased to 5. You can easily imagine, and have probably experienced, scenarios where this is a slippery slope to climbing WIP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How many times have you heard:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;It’s done, it just needs to be reviewed&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In software development, the word “just” is often doing a lot of heavy lifting. &lt;strong&gt;The work is not “done” until it is actually delivering value.&lt;/strong&gt;. The work is still contributing to the team&#39;s WIP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The feedback cycle in the PR can take some time with asynchronous back-and-forth, so you may end up having to switch context between multiple tickets at a time. In lean terms, &lt;strong&gt;the process has caused a bottleneck&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even with a team of only 4 you can easily end up in a situation where they’re context switching frequently. Between the story they’re assigned to, but also reviewing lots of other code written by their team. The personal WIP for each team member can climb steeply depending on how back-and-forth the review process is. As the WIP increases for each person, the ability to get code reviewed diminishes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PRs are remote-friendly due to their asynchronous nature. This is true, but you have to accept then you will have a lot of unfinished work in play, which will raise your team’s WIP.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I were to be managing a team working like this, I think it would be prudent to ensure that you only have 3 developers working on stories at a time, giving your system some slack. The other developer can help reviews happen quicker, find ways to improve flow, increase quality in other ways (improve tests, logging, metrics, e.t.c.), and you’ll have more slack to deal with unplanned work.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Slow integration&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The longer your code lives on a branch, the less integrated you are with the rest of your team. Whilst the 4 of you are described as a team, you are all working on different versions of the code, as individuals.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you find it hard to get your colleagues to review your changes, this slow integration compounds, and teams that adopt this system often have to deal with challenging merge conflicts. In the previous example this way of working can lead to multiple PRs that need merging which can result in multiple merge conflicts having to be resolved. This is &lt;strong&gt;waste&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Unpredictable flow&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The review back-and-forth can last minutes, hours, days, or even weeks. In the worst cases, it involves a lot of re-work. Once the developer falls in to the trap of picking up another story whilst their other is in review, WIP can quickly spiral out of control.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Plenty of successful teams ship software like this, it’s not unworkable, but I’m not convinced it’s simple or efficient. I think even when it is managed extremely well, it still causes a lot of waste.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Trunk-based development (TBD) and pair programming&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What is the most obvious way to reduce WIP?&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do less work concurrently&lt;/li&gt;&#xA;&lt;li&gt;Concentrate on finishing work&lt;/li&gt;&#xA;&lt;li&gt;Increase quality to reduce unexpected re-work&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So instead of having 4 developers work on 4 tickets, let&#39;s instead have 2 developers pairing per ticket.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By having 2 heads work on a problem, it liberates us from having to gate-keep the main branch. We should trust that 2 developers on our team can take ownership of a problem from idea to production. Therefore, they can commit their code straight to main. &lt;strong&gt;This simplifies the flow of work&lt;/strong&gt;. We no-longer have a wasteful bottleneck to shipping value.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;No, I can’t trust 2 developers to take an idea from kick-off to production.&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;How many then? 3, 4? Or worse, can it only be put into the main branch if it is blessed by the lead? If you’re a lead making yourself a bottleneck, you’re not doing a good job. You’re not spreading your knowledge, you’re not coaching well enough, you’re increasing &lt;a href=&#34;https://gist.github.com/quii/30cd1f59b9f05c6f89dbd0e423120644&#34;&gt;bus factor&lt;/a&gt;, and you’re hurting the productivity of your team.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Improved flow, higher quality and less re-work&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;By integrating frequently through the day, the chance of merge conflict is low and even when it happens it is typically trivial to fix. Far easier than having to merge a week’s worth of changes back into main.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is &lt;strong&gt;true continuous integration&lt;/strong&gt;, the team can consistently see what everyone is working on, which helps collaboration. No longer will you hear excuses like:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;I’d like to refactor the blah blah, but I can’t because I know Alice is working on a PR related to it.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;By removing the barriers to changing code and having a tight integration with your team (rather than disparate branches) you can now fearlessly refactor.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s an assumption, but not an unfair one, that the quality of code should be higher if 2 people are working on a change. High internal-quality makes changing our system simpler and should reduce the chance of unexpected re-work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you practice continuous deployment, it means you’ll release smaller changes frequently throughout the day. This reduces risk and makes recovery easier compared to diagnosing a pull request which may have been worked on for a number of days (or weeks!) rather than hours.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The idea of code-review and socialising ideas is now constant and easily available. Developers don’t have to write large amounts of code and then inconvenience another developer, forcing them to context switch to give feedback on your ideas. Instead, you have a colleague that you can easily bounce ideas with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To make sure the socialising of code is spread amongst all developers, we ensure that we rotate the pairs frequently. We’ll also do a “code review” session every week for a couple of hours when we can talk about our code in broader strokes, in a more holistic way; rather than focusing on an isolated change in a PR.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Risk&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If the idea of pushing directly to main is uncomfortable for you, it’s likely you’re working on an unsafe system. For TBD to work, you need to engineer your system so that it is safe to work on. You’ll need things like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Good alerting&lt;/li&gt;&#xA;&lt;li&gt;Easy or automatic rollbacks&lt;/li&gt;&#xA;&lt;li&gt;An excellent test-suite&lt;/li&gt;&#xA;&lt;li&gt;Observability&lt;/li&gt;&#xA;&lt;li&gt;“Test in prod”&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/mipsytipsy/status/1147863838647185408&#34;&gt;If you aren&#39;t testing in prod you aren&#39;t testing in reality -- just a weak dime store knockoff.  Then you light the fuse and walk away with your fingers crossed. Test in prod.  Please.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;— Charity Majors&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Gatekeeping around PRs and releasing is often &lt;strong&gt;reliability-theatre&lt;/strong&gt;. Nothing can save you from mistakes, they’re inevitable. What you need to focus on is your &lt;a href=&#34;https://en.wikipedia.org/wiki/Mean_time_to_recovery&#34;&gt;&lt;strong&gt;mean time to recovery&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To commit to main directly, safely &amp;amp; frequently you need an excellent, fast test-suite and a well configured CI-pipeline. Developers need to be disciplined and only commit code they’re happy to put on the main branch.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Every developer is touching mainline, so all features grow in the mainline… which acts as a communication point. With CI, the mainline must always be healthy, so in theory (and often in practice) you can safely release after any commit.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;— Martin Fowler&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To live with the constraints of wanting to continuously integrate but not make “bad” commits, you need to find ways to break your work down into small, achievable pieces. This discipline makes work more achievable and will &lt;em&gt;reduce&lt;/em&gt; risk. By working like this, I’d expect our 2 pairs of engineers to push several times per day.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Trying TBD&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you do decide to try TBD, be prepared for some friction and growing-pains if you have a team unfamiliar working in this way. &lt;a href=&#34;https://quii.dev/Gamifying_Continuous_Integration&#34;&gt;A few years back, I wrote about how I introduced TBD to a team that was previously familiar with a PR-based approach.&lt;/a&gt;It will be a journey of uncovering issues in quality, bottlenecks and collaborating to find ways to improve them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;TBD may expose some uncomfortable shortcomings in your system, and the quality of your code and architecture. I’ve noticed that often a PR flow masks problems like:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Developers finding it hard to break problems down in to smaller, less risky changes. &lt;a href=&#34;https://cloud.google.com/architecture/devops/devops-process-working-in-small-batches&#34;&gt;They have not learned how to work in small batches&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Low internal quality. If your system suffers from a lot of inappropriate tight coupling, you’ll tend to trip over each other’s toes when working together on the main branch.&lt;/li&gt;&#xA;&lt;li&gt;Poor/inadequate tests. Lots of teams use the “CI server” as a crutch for poorly written tests that they run slowly and infrequently. Every so often, the system is designed in such a way that important tests are impossible to run locally.&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you’re pushing every hour, you need to be able to test locally and be confident your change is shippable and won’t affect your colleagues negatively.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This is a journey that many factories (real factories!) have gone through. To work leanly, with excellent flow, managing WIP requires you to look at &lt;em&gt;how&lt;/em&gt; you do work and commit to increase quality from start to finish as a team.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Which is best for your team?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;TBD is not niche or unusual. Plenty of big businesses, in well-regulated industries, work with pairs of developers committing many times a day to do the main branch. &lt;a href=&#34;https://aboodman.medium.com/in-march-2011-i-drafted-an-article-explaining-how-the-team-responsible-for-google-chrome-ships-c479ba623a1b&#34;&gt;Chromium releases every day and does not use branches&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=bHKHdp4H-8w&amp;amp;feature=youtu.be&#34;&gt;In this short video, Dave Farley shows a fin-tech company in a well-regulated space working with TBD&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Usually, these high-performing teams ship these changes extremely frequently to customers, so they can get real feedback quickly and build superior products.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst pairing may seem like an expensive frivolity, the workflow is simpler, more focused and of higher quality. You’ll find that this approach can out-perform the same team working as individuals on branches. There is plenty of evidence to back up this assertion.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/tastapod/status/1415588779176480770&#34;&gt;Five years&#39; worth of academically defensible State of DevOps research that shows &lt;em&gt;causality&lt;/em&gt; of feature branching with poor performance.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;—  Daniel Terhorst-North&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PRs optimise for individual resource allocation, but introduce bottlenecks in your system which drive up WIP, and make the flow of work less smooth than it could be. &lt;strong&gt;High WIP diminishes a team’s productivity and is a management dysfunction, making work harder than it needs to be.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To those unfamiliar with TBD, it may seem risky and even unprofessional, but it forces you to work with more discipline, adopt best practices which will make your system more resilient and the work simpler.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912&#34;&gt;(Mainline development) is an extremely effective way of developing, and the only one which enables you to perform continuous integration.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;— Continuous Delivery: Jez Humble &amp;amp; David Farley&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Many arguments that dismiss TBD as impractical for their team often are centred around &lt;strong&gt;fear, and a lack of trust&lt;/strong&gt;. If you’re a leader of a team, don’t dodge these issues with walls and process. Deal with it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pull-requests work excellently in the open-source, where you can&#39;t trust external contributors. &lt;em&gt;For your closed-source, day job though? &lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/jezhumble/status/1415908836439773185/photo/2&#34;&gt;Despite abundant evidence that trunk-based development practices contribute to better software delivery performance, some developers who are used to the GitHub-recommended workflow remain skeptical&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;— 2017 State of DevOps Report&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think about &lt;strong&gt;your context&lt;/strong&gt;, examine how work flows through your system, set a WIP limit and stick to it. Find ways to improve the flow and your team’s performance will improve.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 26 Jun 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The TDD Thinking Hats</title>
      <link>https://quii.dev/The_TDD_Thinking_Hats</link>
      <description>&lt;p&gt;When working with people who are learning test-driven development (TDD), I have a habit of talking about “the hat we’re wearing”.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This comes from reading the book &lt;a href=&#34;https://en.wikipedia.org/wiki/Six_Thinking_Hats&#34;&gt;Six Thinking Hats&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The premise of the method is that the human brain thinks in a number of distinct ways which can be deliberately challenged, and hence planned for use in a structured way allowing one to develop tactics for thinking about particular issues.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;When a group wears a particular hat, they engage and discuss an idea in a deliberate way. For instance, if the group wears the yellow hat, they should think positively about an idea, even if that feels unnatural to them. This means everyone explores positives in something, even if individuals within the group have some biases against it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I’ve seen developers who mix up the steps in TDD, where they are refactoring whilst the tests are failing, and they are trying to introduce new behaviour at the same time. These same developers frequently skip the explicit refactoring step too, so they make the whole process more difficult and still end up with code that requires a lot of improvement.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I find trying to have a more focused, deliberate mindset during the TDD steps helps me practice it more effectively, simply, and avoid some common TDD pitfalls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This posts attempts to describe the hats you should wear during the TDD steps.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;TDD &lt;em&gt;feels right&lt;/em&gt; when you’re not wearing any single hat for a long time. If you’re switching through them frequently, that’s telling you that you’re iteratively making positive progress on the system.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;When writing a new test: The green, ambitious hat&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Write the test you want to see&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In this situation, we should be &lt;strong&gt;consumer focused&lt;/strong&gt;, and &lt;strong&gt;optimistic&lt;/strong&gt; about the kind of code we’re going to write.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can be helpful to ask yourself:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If this code already existed in the open-source world, how would I want to use it, and how should it behave?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Try to be &lt;strong&gt;ambitious&lt;/strong&gt;, you get to design a great API by describing how it would be used by a consumer, in this case your test.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Take pride in the test you write, keep asking yourself whether the test describes the what and why effectively. Have &lt;strong&gt;empathy&lt;/strong&gt; for your colleagues who’ll be reading and maintaining these tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At the same time, think about how you can cut scope sensibly, so you are confident that you’ll be able to make the test pass and have this positive change committed to source control in a reasonable amount of time. Have an eye on the end-state, but keep thinking about each small step toward that goal.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Aim to wear this hat frequently, but for short periods, so that you’re working iteratively with fast feedback loops on your decisions.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;But, I don’t feel confident&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is normal! The first step, is often the hardest. There can be numerous reasons why writing a test is difficult:&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;The existing test suite is a hot mess&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Adding a new test to an existing suite can be difficult for various reasons. Perhaps the existing tests are poorly written. Often they are a reflection of poor design, such as lots of complicated mock setup.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This might be time to reflect on the design of the code, and it may be prudent to pick up the blue hat to update the design of your system to facilitate the next change.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;I don’t really know what I’m trying to make&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Talk to your colleagues and stakeholders. Ask them what they think might be the first valuable step. If you don’t understand the problem you’re trying to solve, it’s going to be impossible to write a test for it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may wish to invest some time moving up a few abstraction levels to create an acceptance test to give you a more clearly defined north-star.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;When the tests are failing: The red, uncomfortable to wear hat&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When practicing TDD effectively, you’ll wear this hat frequently, but it should feel deliberate when you do, and &lt;em&gt;you should never be wearing it for very long&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When the tests are failing, &lt;strong&gt;you should feel uncomfortable&lt;/strong&gt;. Your software is not working correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Endeavour to get the tests passing (green) as quickly as possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;You’re not safe to make changes that are not directly related to passing the test&lt;/strong&gt;, as you’ve lost your safety net. Any further changes not dedicated to making the tests pass can make the situation worse by adding confusion and complexity.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Make the test work quickly, committing whatever sins necessary in the process.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;-- Kent Beck&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s important to be thinking about good source control practice. Once you get the tests passing again, commit your changes. If you ended up wearing this hat during refactoring, it’s often better not to be precious about the code you wrote, just revert it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Stop wearing multiple hats at once&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In my experience, many developers wear too many other hats whilst wearing this one in particular, and can make life difficult for themselves because introducing &lt;em&gt;more&lt;/em&gt; changes tends to make the failing test situation worse.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Too often, developers worry too much about writing &amp;quot;beautiful code&amp;quot; and get distracted from our short-term goal, which is &lt;strong&gt;to make the software work&lt;/strong&gt;. We’ll have time to make the code great once we’ve made the test pass.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;When you’re refactoring: The blue, confident hat&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We are free to be &lt;strong&gt;creative&lt;/strong&gt;! Maybe you were thinking about a design with the Red hat or the Green hat on - now is the time you can try it out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We feel &lt;strong&gt;safe&lt;/strong&gt; to make improvements because we get fast and reliable feedback that whatever changes we’re doing are valid. This allows us to aggressively refactor and &lt;strong&gt;take pride in our work&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Make a positive change&lt;/li&gt;&#xA;&lt;li&gt;Verify the change is valid by running your unit tests.&lt;/li&gt;&#xA;&lt;li&gt;Commit the change to source control&lt;/li&gt;&#xA;&lt;li&gt;Go to 1&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;All our efforts are backed by tests against real, desired behaviour, so design decisions we make will be “real”, rather than for imaginary concerns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When wearing this hat we get to improve the code, &lt;strong&gt;experiment and learn&lt;/strong&gt; what works. Be brave and try different approaches to improve the code. If it doesn’t work out, it’s not a problem, as you’ll always be able to get back to working code with a &lt;code&gt;git checkout src/whatever&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Wearing this hat frequently through your day will steadily make you a better developer because you get more chances to experiment and learn.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have an idea for an improvement that you think will take many hours, pause for a moment. It might be worth going through a few more TDD cycles before making this commitment. By adding more tests, and therefore more behaviour; you are giving yourself more concrete information to make better design decisions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like the other hats, don’t let your head get hot wearing it for many hours in a row, as you might end up in a refactoring rabbit-hole. &lt;em&gt;Little and often is the key&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wearing the hats while pairing/mobbing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Six Thinking Hats says that everyone should be wearing the same hat at the same time, so that the group remains focused on the particular task, and you don’t end up moving in different directions and getting distracted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For instance, the group could be wearing the red hat, but you can see a way the code could be improved. Don’t break the group’s flow, just take a note and bring it up when you’re all wearing the blue hat. Remember, if you’re practicing TDD well, you’ll be switching hats frequently through the day.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you’re a more experienced member of the group, perhaps you can try using this thinking tool as a way of moderating how your team works through a problem more deliberately, and with better focus.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Do you wear these hats?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To those who feel confident and proficient with TDD, do these feelings and behaviours resonate with your experience? Do you disagree or do you have anything that’s missing here? &lt;a href=&#34;https://twitter.com/quii&#34;&gt;Please reach out to me on Twitter&lt;/a&gt;.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 25 Jun 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Go Time - Giving TDD a Go</title>
      <link>https://quii.dev/Go_Time_-_Giving_TDD_a_Go</link>
      <description>&lt;p&gt;I was lucky enough to have a second appearance on the Go Time podcast a few weeks back. Riya, Dave, Mat and I talked about TDD.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I enjoyed it! Don&#39;t think I waffled &lt;em&gt;too&lt;/em&gt; much but as Mat said, it felt like we only scratched the surface.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://changelog.com/gotime/185&#34;&gt;You can have a listen here&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 24 Jun 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Three Books</title>
      <link>https://quii.dev/The_Three_Books</link>
      <description>&lt;p&gt;&lt;a href=&#34;https://twitter.com/gypsydave5&#34;&gt;David Wickes&lt;/a&gt; wrote an excellent post called &lt;a href=&#34;https://dev.to/gypsydave5/three-books-fb6&#34;&gt;Three Books&lt;/a&gt;, which claims that any senior developer should be able to recommend three books to a less experienced colleague. There are various reasons for this and some nuance, so please read the post!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wish I had been lucky enough or had the foresight to read these books when I was 25. I’ve tried to pick three varied books that give you solid foundations to be a good software developer.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;a href=&#34;https://itrevolution.com/the-phoenix-project/&#34;&gt;The Phoenix Project&lt;/a&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This helps you understand there’s so much more to shipping software than raw technical skills.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Making anything non-trivial requires teamwork. This brings social and organisational challenges.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These are different from what you learn in a computer science degree. This book helps you see these issues, the dysfunctions organisations can get into, and how to get past them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you understand the concepts in these books, you’ll be able to help your team work better and be more likely to have successful projects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After reading this book, if you enjoyed it and found it helpful, I’d go straight into reading &lt;strong&gt;The Unicorn Project,&lt;/strong&gt; which is the successor, but from a developer&#39;s point of view.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The Unicorn Project is the organizational civil-war novel that every technology and business trailblazer must read.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Christopher O’Malley&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;a href=&#34;http://www.growing-object-oriented-software.com&#34;&gt;Growing Object-Oriented Software guided by Tests (GOOS)&lt;/a&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I read this book long after working with &lt;a href=&#34;https://www.thoughtworks.com&#34;&gt;ThoughtWorks&lt;/a&gt; (TW), a software consultancy company. For many years they worked with the company I was in, coaching us on how to write software the modern way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Before this, I was mainly a solo developer, bashing code out and copying it to prod on small websites. TW taught us how to work on big projects, which requires you to work entirely differently due to the different challenges working as scale brings.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Reading GOOS, it’s apparent that it’s a blueprint for what TW taught me and what I have been coaching my team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It would be a long post if I were to talk about everything they introduced, but some core values were:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Working on big things is hard. So cut scope, break the problem down and work iteratively.&lt;/li&gt;&#xA;&lt;li&gt;TDD&lt;/li&gt;&#xA;&lt;li&gt;Fast feedback loops&lt;/li&gt;&#xA;&lt;li&gt;Pair programming&lt;/li&gt;&#xA;&lt;li&gt;Trunk-based development&lt;/li&gt;&#xA;&lt;li&gt;Heavy emphasis on automation&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Yes, it’s a book about TDD, but it feels more significant than that. It’s a practical book showing how to build a real, complicated thing in what I would consider &lt;em&gt;the right way&lt;/em&gt;. Many people lament that too many TDD articles are simplistic and not “real world”. The answer to that whining is this book.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&lt;a href=&#34;https://www.informit.com/store/refactoring-improving-the-design-of-existing-code-9780134757599?ranMID=24808&#34;&gt;Refactoring (2nd ed)&lt;/a&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I have no evidence for this, but anecdotally, most developers don’t know how to refactor very well. Many don’t even know what refactoring is. Most aren’t refactoring anywhere near enough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The good news is, if you study this relatively short manual on refactoring, you’ll level yourself up as a developer. Once you understand what refactoring is and practice what is explained in this book regularly, you’ll improve the code you work on. You’ll increase your and your team’s productivity, and refactoring will reveal better designs for your system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you’re a developer who claims, &amp;quot;I don’t have time to refactor&amp;quot;, &lt;strong&gt;you’re wrong&lt;/strong&gt;. Your definition of refactoring is likely incorrect, and you certainly don’t know how to practice it effectively.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Honorable mentions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;These were books that were very influential in my development. However, I recognise my juniors are very time-starved and suffer from vast information overload. These books are great, but they should probably only be picked up if they catch the individual’s eye.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/The_C_Programming_Language&#34;&gt;The C Programming Language&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This may be a function of sentimentality, as C was the first language I properly studied.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s a wonderfully short book and easy to read, but at the same time, it goes deep into how your computer works.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The big thing you’ll have to overcome is the concept of variables that are the actual data and variables that &lt;em&gt;point&lt;/em&gt; to data. This requires you to leap across a somewhat abstract thinking barrier, but it’s essential to make it, and it’s applicable outside of C.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://www.amazon.co.uk/Functional-Programming-Scala-Paul-Chiusano/dp/1617290653&#34;&gt;Functional Programming in Scala&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Writing your abstract data types like Option, List etc., will help you realise that a lot of functional programming (FP) is not all that complicated. It’s a fun book and taught me much of my FP knowledge.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://www.poodr.com&#34;&gt;Practical Object-Oriented Design in Ruby (POODR)&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sandi Metz teaches what it means to be a good developer from a technical and behavioural standpoint.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We are similar in respect of not tolerating bad excuses for poorly written code. Her discussion about the importance of exemplary code has stuck with me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;She shows you how to write good, object-oriented code throughout the book. Like refactoring, there’s a lot of talk about OO from thought leaders on the internet, but most of the time, it’s clear that the person’s idea of what OO is wildly different from what is written by experts, like Sandi.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OO gets a lot of negative press these days, mainly due to the faddy nature of our industry.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Function good, class bad.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This book is relatively short and gives you an excellent intro to OO.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Don%27t_Make_Me_Think&#34;&gt;Don’t Make Me Think&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A common sense approach to web usability&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you wish to describe yourself as “full stack”, you should acknowledge that you won’t be an expert at everything but should appreciate all aspects of your craft.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This book will help improve your empathy for users and give you some practical ways to ensure the website you’re making works well.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In this second edition, Steve Krug adds essential ammunition for those whose bosses, clients, stakeholders, and marketing managers insist on doing the wrong thing.  If you design, write, program, own, or manage Web sites, you must read this book.&amp;quot;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Jeffrey Zeldman&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://pragprog.com/titles/mnee2/release-it-second-edition/&#34;&gt;Release It!&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I read the first edition of this book a while ago; a 2nd edition was released in 2018.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For someone who had previously been manually copying code into production without a second thought, it taught me what it takes to release and operate systems at scale.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing code is one thing, but creating sustainable and straightforward systems is a skill that needs to put more effort into learning and improving.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It introduced me to the &lt;a href=&#34;https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern&#34;&gt;circuit breaker pattern,&lt;/a&gt; which is a pattern for isolating failures. It keeps small failures small rather than escalating and taking down your entire system. You&#39;ll find this pattern in most modern, web-scale systems, and often now it&#39;s built into things like &lt;a href=&#34;https://istio.io/latest/docs/tasks/traffic-management/circuit-breaking/&#34;&gt;Istio&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are many more gems like this; it&#39;s worth reading.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 19 Jun 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Interview questions as a candidate</title>
      <link>https://quii.dev/Interview_questions_as_a_candidate</link>
      <description>&lt;p&gt;No matter what my role is within a company, I want to work in an empowered, trusted, team that works together to deliver things we can all be proud of.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Old-fashioned “command and control” hierarchies or completely misunderstood applications of agile have caused misery for people working under them, and do not result in successful products. I want to avoid working in those kinds of environments.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These questions won’t always be relevant for every company. A 2-person startup probably doesn’t have the notion of a product owner (the 2 people are implicitly the POs!) but I feel the &lt;em&gt;principle&lt;/em&gt; of most of these questions stand.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Who decides priority of work?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A product owner, guided by research and UX practitioners, assigns hypothetical value to stories — but the team decides what to work on, so they can decide how best to deliver value. That might include playing spikes, addressing technical debt etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It should be a collaborative relationship between product people and engineers.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Teams with no autonomy eventually fail. Software engineers are paid the mega-bucks to solve problems, not blindly work through tickets. Without autonomy the wrong things are prioritised, productivity tumbles and systems will fall apart.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;PO as manager&lt;/li&gt;&#xA;&lt;li&gt;Feature factories&lt;/li&gt;&#xA;&lt;li&gt;Spiralling technical debt&lt;/li&gt;&#xA;&lt;li&gt;Bad relationship between engineering and product&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;How are users’ problems solved?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The end user is at the centre of what the team does. User stories are &lt;em&gt;user stories&lt;/em&gt;, a brief amount of text trying to convey what problems the user is trying to solve and why.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People from all disciplines get together, discuss it, figure out what needs to be done to try to solve the problem and figuring out ways to know if we’ve succeeded. Ideas include,&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;UX team reaching out to users for interviews&lt;/li&gt;&#xA;&lt;li&gt;Developers creating cheap prototypes along with thinking about possible long-term solutions&lt;/li&gt;&#xA;&lt;li&gt;The team going back and admitting that they don’t understand the problem rather than just blindly building something&lt;/li&gt;&#xA;&lt;li&gt;A story typically is not finished with a release of software. Many iterations are made to gather feedback to learn how to solve the problem better for the user.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This style of working gets everyone invested in the project and feeling involved.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This environment is where real innovation comes from because smart people have a better understanding of the domain and have the space to solve real problems.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A select group of individuals looks at user’s problems and generate numerous tickets in JIRA for technical people to administer. Developers have little to no idea the purpose of the work and cannot offer feedback on what is being worked on.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Story robots&lt;/li&gt;&#xA;&lt;li&gt;Feature factories&lt;/li&gt;&#xA;&lt;li&gt;Bad products&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The tickets have very little resemblance to stories and are instead barely validated, overly specific, solutionised tasks for developers to work on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Work “happens”, arbitrary targets met, but both users and development teams are not happy.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;What’s the general makeup of experience? Do you hire many juniors? How heavily white and male is your engineering department?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Hiring from a diverse range of experience gives us a diverse team, which is a good thing in terms of productivity, environment and &lt;em&gt;being the right thing to do&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Seniors should feel proud to help less experienced people grow, and the juniors help challenge assumptions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An environment of continuous learning with coaching and mentoring is &lt;em&gt;just nice&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Often people who have worked for less than &amp;lt;5 years have had a bigger impact on me and the teams I’ve worked in than the engineers with 10 years.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Don’t have time to train people. What else do they not have time for? We &lt;em&gt;all&lt;/em&gt; need training and space to think regardless of experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I want to work in an environment that encourages and supports people from any background. If your engineering teams do not have any female leaders for instance, that is a bad sign.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How often do you release? Who releases?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Feedback loops are so important in software and product development. Whether its feedback given by customers, or realising something you’ve shipped has introduced a bug; the sooner you get this feedback, the cheaper and easier it will be to act on it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Developers should be in charge of releasing code, and because of that they’re forced to write good automated tests and having excellent operability. They should be focused on optimising for a reliable, quick release pipeline so they can make changes to the software frequently and safely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Product owners &lt;em&gt;can&lt;/em&gt; be in charge of features becoming visible to users if that’s needed (e.g., use feature flags), but copying code from one server to another is a technical concern, not a product one.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You are continuously delivering code to production on green builds. This question will also tell me about your testing approach (or lack of!).&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;h4&gt;Manual testing&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Points to a lack of thought as to how to deploy software safely.&lt;/li&gt;&#xA;&lt;li&gt;Usually coincides with poor engineering, lack of automated tests begets lack of high internal quality.&lt;/li&gt;&#xA;&lt;li&gt;Doesn’t scale.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;Gatekeeping (release managers, or some kind of sign-off step):&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Lack of trust.&lt;/li&gt;&#xA;&lt;li&gt;Empire building.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;Lack of DevOps culture&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;If you have a “DevOps team” who are in charge of releasing software then I suggest you read a book about DevOps because you have missed the point. Focus on the principles, not the tools.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Do you have delivery / project managers? What do they do?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Project managers (PMs) can be extremely useful with coordination across bigger sets of people, helping to understand X team dependencies. They often do a lot of “glue work” for the team to help them work more effectively.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;quot;Striving to ensure that no resource be idle is the biggest generator of waste.&amp;quot; —Eli Goldratt&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;PMs are incentivised to “maximise developer output” and the company has no idea what the value of slack is. If your team is always running at 100% capacity, how do you expect it to improve? Hint, repeatedly cracking a whip will not improve your team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Slack is critical and is widely written about. It’s weirdly ignored by a lot of project managers. &lt;strong&gt;Teams running at full capacity all the time are brittle&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;“Projects” are poison to good software. What happens after your deadline?&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Implies no feedback loop with customers, just ship stuff for hitting deadlines sake rather than doing something useful.&lt;/li&gt;&#xA;&lt;li&gt;Bad incentives. Celebrate hitting deadlines but won’t talk about whether the product is actually worthwhile.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If they dictate priority they’re just as bad as POs as bosses.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Do you have QAs? What do they do?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you do, they are there to act as coaches in respect to how to build high-quality systems (think testing, operability, etc). They also might be individuals who have time and space to do exploratory testing to find new insights about the system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;QA should be a responsibility shared by the team, not a role.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Separate individuals writing tests&lt;/li&gt;&#xA;&lt;li&gt;Gatekeepers&lt;/li&gt;&#xA;&lt;li&gt;Army of manual testing which leads to slow releases, slow feedback loops, etc&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Do you have UX engineers? What do they do?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;UX are researchers and educators.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They reach out to users and learn about their needs, often they’ll bring other disciplines such as engineers with them, so they also gain first-hand appreciation of the problems you’re trying to solve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there they work with the team to figure out how to solve these problems.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’ll often find the UX people sat with engineers scribbling on paper to agree upon cheap experiments to try to understand these problems.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The UX team revel in learning, striving to learn more about users and then documenting and presenting their findings.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The discipline of UX is conflated heavily with visual design.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Rather than actually thinking about the &lt;em&gt;user’s&lt;/em&gt; problems they are trying to solve, they spend more time worrying about making pixel-perfect designs for the &lt;em&gt;product owners&lt;/em&gt; to rubber-stamp. This is a real waste of talent and energy, they’re UX experts to serve the users, not the whims of POs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This way of working leads to costly feedback loops where engineers have to implement these pixel-perfect solutions only to find they are impractical in some way, or don’t actually meet the user’s needs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Often they seem not attached to the software team, rarely collaborating or learning with the team. Instead, they’re working very far in to the future making mockups for software you may not even write.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All of this looks like siloed work in a waterfall project.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How do you validate your work? What makes you decide to start initiatives? What makes you end initiatives?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You have a vision to guide your company but acknowledge there’s lots to learn. Mistakes are fine so long as you learn from them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You have a learning environment, you’re always pushing for faster more effective feedback loops. A part of this is trying to find ways to cheaply validate ideas, and you lean on your software development teams to help you do this.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’re not afraid to cancel an initiative or change it radically if you need to. Plans are changing all the time, driven by these learnings.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Empowered and involved teams bring ideas that are also prioritised&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/cliffhazell/status/1285477573238104064&#34;&gt;Good ideas don’t arrive during quarterly planning&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Customers are involved and we work with them closely to help build a great product.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Immutable product roadmaps&lt;/li&gt;&#xA;&lt;li&gt;Long backlogs&lt;/li&gt;&#xA;&lt;li&gt;Optimising for predictability over good products&lt;/li&gt;&#xA;&lt;li&gt;Development team feeling disempowered and uninspired&lt;/li&gt;&#xA;&lt;li&gt;Lack of feedback loops&lt;/li&gt;&#xA;&lt;li&gt;Lack of end-user involvement, if at all.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Can we stop selling people things that aren&#39;t possible to deliver? Please?&#xA;Users and customers &lt;em&gt;need&lt;/em&gt; to be involved in development of &lt;em&gt;their&lt;/em&gt; software.&#xA;If you don&#39;t want to be involved, you can&#39;t complain when the resulting software doesn&#39;t work for you.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/ChristinGorman/status/1289887336256307201&#34;&gt;https://twitter.com/ChristinGorman&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Do you have fixed deadlines?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Obviously, we don’t have infinite money but working to a strict deadline implies a lack of feedback loops.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We prefer to keep iterating quickly and keep gathering feedback. If we learn that what we’re doing is useful, we’ll keep investing until we (and the customers) are happy with it. Has the Twitter “project” finished yet?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Rather than deadlines instead think:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;How much of our budget are we willing to spend on this idea?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Whilst a &lt;em&gt;bit&lt;/em&gt; of pressure is good, tight deadlines are toxic. It usually results in teams rushing out poor quality systems that are difficult to maintain and because of the fixed nature of work the technical debt will remain unaddressed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Inevitably the system needs changing at some point (by another absurd deadline, again), repeat cycle of doom forever. Engineers get further blame as things become more and more difficult as technical debt spirals out of control.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Who is supporting the software after you release it?&lt;/li&gt;&#xA;&lt;li&gt;Is it really worthwhile to build if you’re not going to change it to adapting customer needs? Again, is the Twitter project finished? Is the Facebook project finished?&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Hitting deadlines is not a goal in itself.&lt;/strong&gt; Too many companies fetishise hitting deadlines (which are often &lt;em&gt;totally arbitrary &lt;/em&gt;) over building good products and having healthy, meaningfully productive teams.&lt;/li&gt;&#xA;&lt;li&gt;If you use tight deadlines as “motivation”, you have big problems. Why aren’t people intrinsically motivated at all? Why can’t you treat your colleagues as adults and trust them? Can the management seriously not think of other ways to motivate people?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Do you have 10% time?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Yes, we give space for engineers to learn because we recognise that self-improvement is vital to the success of the business.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In addition, we believe it helps with diversity. A young white male with no responsibilities can spend his free time learning the latest, greatest programming languages, but that’s not going to be true for a single mother.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Lack of time? Again, why are projects so poorly managed that there’s no time for the team to improve?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How do you expect the team to improve and be able to hit your aggressive deadlines if they’re always working at full capacity? You should view your development teams as important assets that you want to invest in.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Who is in charge of process? Is there a standard way across teams?&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Ideal answer&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The team(s) are in charge of their process. Teams are groups of different individuals working on different problems and if they have a positive, learning-led culture they will retrospect and refine the way they work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;They are trusted and incentivised to find better ways of working&lt;/strong&gt;. Kaizen is at the heart of every team’s culture and a result of that is inevitably teams will work differently.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some standardisation is helpful though, maybe every team is obliged to showcase their work every week for instance. However, &lt;strong&gt;standardisation never trumps a team’s ability to improve the way it works&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Warning signs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An answer of “Yes there is a standard process”. Teams are different and need to be empowered to improve their working practices, or they wont be able to adapt to changing circumstances.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst developers being able to move between teams is &lt;em&gt;nice&lt;/em&gt;, prioritising it over autonomy will be extremely costly. Think about what a standard process involves. There has to be some kind of governance for it. If a team &lt;em&gt;needs&lt;/em&gt; to change the process to work more effectively, how time-consuming will that change take and how chaotic will that be for the &lt;em&gt;other teams&lt;/em&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s pretty laughable how many companies will blindly follow ceremonies like retrospectives and simultaneously not allow them to act on whatever they uncover because of &lt;em&gt;the process&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Quickfire questions about managers&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do they enjoy the job? Or were they pressed into it. What do they like?&lt;/li&gt;&#xA;&lt;li&gt;Do they have access to training? Management isn’t an inherent skill, it is something that needs to be studied and practiced.&lt;/li&gt;&#xA;&lt;li&gt;How often do they have 1 to 1s, skip level meetings?&lt;/li&gt;&#xA;&lt;li&gt;Does your manager care about you? Have they helped move your career forward?&lt;/li&gt;&#xA;&lt;li&gt;Has your manager said no to you?&lt;/li&gt;&#xA;&lt;li&gt;Can your manager actually make decisions? Or are they just a communication funnel?&lt;/li&gt;&#xA;&lt;li&gt;How do you grow your reports?&lt;/li&gt;&#xA;&lt;li&gt;Why did you become a manager?&lt;/li&gt;&#xA;&lt;li&gt;When has a manager batted for you?&lt;/li&gt;&#xA;&lt;li&gt;Has your manager ever given you hard to hear feedback?&lt;/li&gt;&#xA;&lt;li&gt;Talk about a team member’s growth they are proud of&lt;/li&gt;&#xA;&lt;li&gt;Talk about when they got negative feedback from someone on their team, and how did they deal with it?&lt;/li&gt;&#xA;&lt;li&gt;What’s the biggest challenge your team faces, and what are you doing about it?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h1&gt;What if you answered a lot of the questions above “wrong”?&lt;/h1&gt;&#xA;&#xA;&lt;p&gt;Does your organisation have the maturity and honesty to see its own short-comings? How willing is it to change? Who is sponsoring this change? Are they actually in charge, can they make decisions?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I’ve often found there are numerous people who are asking the right questions, but they’re at the wrong level at the organisation. They’re often fighting bad incentive structures. For instance, when an organisation hires and incentivises people to prioritise hitting arbitrary deadlines at the cost of everything else it’s going to be very hard to improve things.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I’ve worked in environments that have answered many of these questions poorly, but they have a good enough environment and autonomy to let us all make positive changes. So, I’m not looking for 10/10 but a willingness to improve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Being involved with teams that have driven positive change have been the source of a lot of pride for me. The nature of our industry means all teams/orgs have to constantly adapt to deal with new circumstances. The open-minded, honest, diverse organisations are the ones that are best equipped for this reality.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 04 Jun 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Why of TDD</title>
      <link>https://quii.dev/The_Why_of_TDD</link>
      <description>&lt;p&gt;Many people have false starts with test-driven development (TDD). When I discuss it with people, many have some misunderstandings around the method, in particular the motivations behind it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I believe if developers have a better understanding of why to use it, they’ll have a better chance of practicing TDD more effectively and get more value out of it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This posts explores the reasons for using TDD and offers some guidance as to how to practice it more effectively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was invited to speak about this topic at the GoSG, a meet-up for the Go programming enthusiasts in Singapore. &lt;a href=&#34;https://www.youtube.com/watch?v=-VKs3rrSHF8&amp;amp;t=2714s&#34; title=&#34;https://www.youtube.com/watch?v=-VKs3rrSHF8&amp;amp;t=2714s&#34;&gt;You can find the recording on YouTube&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;http://www.growing-object-oriented-software.com&#34;&gt;This post quotes Growing Object-Oriented Software Guided by Tests (GOOS)&lt;/a&gt; (written by Steve Freeman and Nat Pryce) extensively as it aligns very closely with how I was taught TDD. I strongly suggest grabbing a copy and giving it a read. Ignore that the examples are in Java, the main lessons from the book are broadly language-agnostic.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Introduction&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you’re new to software development, there’s several knowledge hurdles you need to leap over. The one you’ll be judged on the most is your ability to use the tools in front of you to get stuff working and get it to the customers. How well you do this and how delightful the result can be referred to as &lt;strong&gt;external quality&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you get proficient at this, the main challenges facing mid-level and above are to do with &lt;strong&gt;internal quality&lt;/strong&gt;. This focuses on your ability to work on and design systems so that the cost of change is reasonable. This is important because if a system is useful, it will have to change over its lifetime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When talking to non-technical folk about this, you can use an analogy of the quality of a factory, and its equipment. If parts of your machinery are unreliable or hard to deal with, the factory will begin to grind to a halt. This is also true of software. &lt;strong&gt;If internal quality declines, the ability to affect the external quality of the software will decline too&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are a lot of software developers out there who can bash the code out enough to make useful software. A problem in our industry is we’re often incentivised and praised by our ability to work through “tickets” quickly and trying to hit (often arbitrary) deadlines. Frequently though, the internal quality gets neglected, and we hear these stories over and over again:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Why is the estimate for changing the system 3 weeks? It should be 3 days!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We need to spend a month re-writing the Foobar module.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I can’t stand to work on this legacy system again. Please let me move to a different project, or I’ll find somewhere else to work.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;There are fewer developers who can write software that can live for many years without painful re-writes and staggering maintenance costs. The reason simply is, it’s really hard. It requires effort and study. I’ve been writing software for over 15 years and I still find it hard and feel the need to keep studying and reflecting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are developers and stakeholders who have advanced skills in justifying reasons for not caring about internal quality. They’ll say things like:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The only thing that matters is working software&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What about time to market?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;All&lt;/em&gt; worthwhile systems have to be changed (see &lt;a href=&#34;https://en.wikipedia.org/wiki/Lehman&#39;s_laws_of_software_evolution&#34;&gt;Lehman’s laws of software evolution&lt;/a&gt;). &lt;strong&gt;“All that matters is working software” can’t be used as an excuse for poor internal quality today when you will have to change the external quality tomorrow.&lt;/strong&gt; People tend to under-estimate the costs of poor internal quality and &lt;em&gt;over-estimate&lt;/em&gt; the cost of keeping internal quality high.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You need to be thinking about the design of your system because the problem you are solving is different to everyone else’s. Domain knowledge (or lack-of) has a giant impact on what designs are suitable, so no single blog post can tell you how to design &lt;em&gt;your&lt;/em&gt; system. It’s your responsibility as an engineer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Many developers work in environments which have a real fear around speed of delivery, and you can get tempted in to short-term promises of productivity. A new programming language! &lt;a href=&#34;https://dev.to/gypsydave5/why-you-shouldnt-use-a-web-framework-3g24&#34;&gt;A shiny new framework&lt;/a&gt;. Even folder structures in the Go community seem to be endlessly discussed as some kind of silver-bullet to good software. Chasing these things is a distraction and is not equipping you to strengthen your skills at writing software with high internal quality, you’re just learning &lt;em&gt;another thing&lt;/em&gt; that will be unfashionable in a few years.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is why I think TDD is such a valuable method. It gives you a structured way to confront and think about the internal quality of &lt;strong&gt;your&lt;/strong&gt; system. TDD is a skill which can work in any context, &lt;a href=&#34;https://twitter.com/quii/status/1396731981698842625&#34;&gt;even on Mars&lt;/a&gt;. It is an excellent tool for training yourself and your team to design better software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;TDD can be seen as a developer frivolity that slows teams down. This is true when you are first learning it (like any skill) but with practice and training, you’ll find yourself working at a sustainable pace and consistently delivering value. &lt;strong&gt;High internal quality will facilitate improvements to external quality&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/adamluzsi&#34;&gt;Adam Luzsi &lt;/a&gt;points out:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;… most people who start to learn TDD, are also in the process of learning software design implicitly through TDD. And this causes the feeling of &amp;quot;this slows me down&amp;quot;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;High internal quality is not exclusive to practitioners of TDD but if you’re on the fence about TDD I hope this post encourages you to take another look. Maybe at least make you reflect on your own methods for writing great software.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;What is TDD?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Test-driven development is conceptually simple to follow:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Write a test for a small, desired behaviour&lt;/li&gt;&#xA;&lt;li&gt;See it fail&lt;/li&gt;&#xA;&lt;li&gt;Write just enough code to make it pass&lt;/li&gt;&#xA;&lt;li&gt;Refactor&lt;/li&gt;&#xA;&lt;li&gt;Go to 1 for next increment of behaviour&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;Yet, there appears to be many developers diverging a lot from what was described by Kent Beck and others.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This inconsistency makes discussing the merits of TDD difficult because every so often what someone believed to be a typical TDD process seemed to be following a TDD-like process but getting key parts of it wrong.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why does this happen? I think tech in general suffers a problem of being extremely faddy and people not really understanding &lt;em&gt;why&lt;/em&gt; they are adopting a particular framework or technique. &lt;strong&gt;If you don’t understand what TDD is for, you’re unlikely to practice it effectively.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;So, why test-driven development?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Here are the typical answers you’ll get:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Prevent defects&lt;/li&gt;&#xA;&lt;li&gt;Good test coverage&lt;/li&gt;&#xA;&lt;li&gt;Confidence to refactor&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Rightly some will argue:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;These benefits are not unique to writing tests first&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2&gt;Why write tests &lt;strong&gt;first?&lt;/strong&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It’s worth exploring the why of TDD in detail as I believe it helps clarify &lt;strong&gt;how to use the method effectively&lt;/strong&gt;. Many people have false starts with TDD.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;GOOS picks up on this:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“We’ve seen teams that write tests and code at about the same time where the code is a mess and the tests just raise the cost of maintenance. They’d made a start but hadn’t yet learned that the trick … to let the tests guide development.”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3&gt;You have to know what behaviour you’re trying to build to write a test&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Developers go too fast, diving in to code and letting their imaginations run wild.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://twitter.com/jocrossick&#34;&gt;Jo Crossick on Twitter&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;When I write tests first, it&#39;s because I know that I&#39;m itching to write over-complicated, over-ambitious code that is destined to become a hot mess, and tests is the only thing that can hold me back from creating instant technical debt&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;A lack of method to the design process can lead to software designed against loose, ill-defined requirements. This design can quickly become a drag on the team’s productivity. It can confuse developers, baking-in to your system assumptions that are untrue and behaviours that aren’t actually needed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing a test first &lt;strong&gt;demands you precisely define, and focus on what you’re trying to achieve; this is a key part of the design process&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing a test first means you have to:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;remove any ambiguity, meaning you have to &lt;strong&gt;really understand the behaviour you need&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;cut down the scope to a small piece of useful functionality, &lt;strong&gt;liberating you from having to design the whole system&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Rather than having to be somehow clever enough to know all the requirements the system would ever need and committing to a design, instead you design code for behaviour you have precisely defined. You design, for one thing at a time, and you do it properly.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It offers a fast and continuous feedback loop on your design&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Writing a test gives you a sense of the design of a particular unit &lt;strong&gt;at the beginning&lt;/strong&gt;. Many developers will dive in, creating types and abstractions for hours on end and only when they plug it all together and run their application do they begin to see the flaws in their design. &lt;strong&gt;Until code is executed and the behaviours observed, the design has had no &lt;em&gt;real&lt;/em&gt; validation&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With TDD you get feedback at the start and as you iterate through more behaviour you will keep getting guidance from your tests. There is no faster way of getting feedback on your design than by declaring what success looks like at the start.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You will have a sense of progress as you take small, validated steps toward your goal. If practiced well, you won’t end up in situations of having to throw hours or days worth of code away.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whilst not being unique to &lt;strong&gt;test-first&lt;/strong&gt;, tests reflect your design back at you. If a test is difficult to read or write, it is telling you something. A key skill for practicing TDD well is to &lt;strong&gt;listen to your tests&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It gives you momentum and by focusing on internal quality will help you continue to change your software cheaply.&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Many developers “spin many plates”, darting from one part of the code to the other, changing different bits of code and in general working in a fairly chaotic way. This way of working makes life difficult and more prone to error and re-work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Writing a test first acts as a stabiliser&lt;/strong&gt;. This sets you a clear, short-term objective and lets you focus on doing one thing well, rather than worrying about competing concerns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The refactoring step improves your chances of maintaining good internal quality which is &lt;em&gt;essential&lt;/em&gt; for a system to be malleable. We’ve all worked on systems where the internal quality is terrible and how frustrating it is how difficult it can be to make a seemingly simple change.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The iterative nature of TDD means you keep working on achieving one small improvement at a time.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;It does not slow you down&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.geepawhill.org/2018/04/14/tdd-the-lump-of-coding-fallacy/&#34; title=&#34;GeePaw has an excellent video which dispels the idea that TDD slows you down. In fact it&#39;s the opposite when you forget about the silly idea that software development&#39;s bottlneck is simply typing code.&#34;&gt;https://www.geepawhill.org/2018/04/14/tdd-the-lump-of-coding-fallacy/&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;GeePaw has an excellent video which dispels the idea that TDD slows you down. In fact, it&#39;s the opposite when you forget about the silly idea that software development&#39;s bottleneck is simply typing code. &lt;strong&gt;Thinking is the bottleneck&lt;/strong&gt;, we work in a knowledge-based field and TDD offers us a way to think with clarity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s true that when you first practice TDD you will go slower than before. In cases where maybe your design skills aren’t as strong as you think, TDD may feel frustrating, but you can use it as a tool to improve your ability to write modular code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s a skill that has to be learned and practiced but with time you’ll find yourself working quicker, confidently and with more focus.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The qualities required to make code unit-testable are good qualities in themselves&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;GOOS:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“…the effort of writing a test first also gives us rapid feedback about the quality of our design ideas—that making code accessible for testing often drives it towards being cleaner and more modular.”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Modular code is:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Easy to repurpose and re-use within different contexts&lt;/li&gt;&#xA;&lt;li&gt;Focused&lt;/li&gt;&#xA;&lt;li&gt;Simple to test&lt;/li&gt;&#xA;&lt;li&gt;Small, with clear responsibility&lt;/li&gt;&#xA;&lt;li&gt;Easy to understand&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Many developers have a healthy skepticism to premature abstraction, but it can go too far.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is not good to have that &lt;em&gt;what&lt;/em&gt; and the &lt;em&gt;how&lt;/em&gt; of code mixed up within a function featuring 100s of lines of code, with mixed up and complected concerns. Rich Hickey covers the topic of easiness vs simplicity in his incredible talk &lt;a href=&#34;https://www.infoq.com/presentations/Simple-Made-Easy/&#34;&gt;Simple Made Easy&lt;/a&gt;. Having all your code in one method is “easy”, but it is not simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Systems built up of modular, &lt;em&gt;cohesive&lt;/em&gt; units are simpler to understand and easier to change.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It’s easier to write good tests beforehand&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Writing tests after the code is written is challenging to get right. You can end up with tests that may not fail when you want them to, have cryptic error messages or simply not have good coverage. You’ll also fall in to the trap of testing your design, rather than the behaviour (more on this later).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing tests first and seeing them fail helps you validate their usefulness and helps you focus on testing from the consumer’s point of view, rather than the person who wrote it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It requires you to constantly refactor&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A key, but often skipped step by novices is the refactoring step. It is far easier and more sustainable to do frequent, small refactors around the code you’re actually working on throughout the day, rather than leaving it for “a refactoring/technical-debt sprint”.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ill-factored code makes the system harder to re-design. Often the &lt;em&gt;act&lt;/em&gt; of refactoring reveals designs. As you consolidate code and DRY things up you start to “see” abstractions that can simplify matters.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Digression: Refactoring sprints are an absurd idea and point to some real team disfunction&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You want the benefits of increased internal quality &lt;strong&gt;now&lt;/strong&gt;, not in 3 weeks time.&lt;/li&gt;&#xA;&lt;li&gt;Everyone knows they are hard to do and frequently fail to give the pay-off you’d hope for.&lt;/li&gt;&#xA;&lt;li&gt;It’s your job to maintain internal quality because &lt;strong&gt;that’s what helps you deliver external quality at a reasonable cost&lt;/strong&gt;. Don’t ask for permission to do your job.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt; How to use TDD&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Work iteratively, in small positive steps&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Working on a single, small, well-defined thing is simple, and you’re more likely to succeed. You’ll get fast feedback on whether you’re going in the right direction.&lt;/li&gt;&#xA;&lt;li&gt;Working on many, large, loosely defined things at once is difficult, and you’re more likely to make mistakes. The feedback loop is slow.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;When practicing TDD you should always be thinking about how to reach the vague end-state with specific, achievable steps. If you’re writing a unit test that you know will take hours of effort to make it pass, you need to rethink your approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can be challenging to break work down into small steps, and it will also challenge your design skills but working this way means you are more likely to succeed, and you’ll reduce waste.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;When TDD feels right&lt;/h4&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Constant, small progress throughout the day. Never feels slow, feels deliberate.&lt;/li&gt;&#xA;&lt;li&gt;Frequent commits to source control per hour.&lt;/li&gt;&#xA;&lt;li&gt;Work feels “safe”, less chaotic than maybe you’re used to.&lt;/li&gt;&#xA;&lt;li&gt;Mistakes are rarely large. Happy to revert changes if you realise you’ve gone down a wrong path.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Writing the test first&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There’s a difference between knowing to write a test first and doing it in a way that helps you design your software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;GOOS:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;“We want each test to be as clear as possible an expression of the behaviour to be performed by the system or object. While writing the test, we ignore the fact that the test won’t run, or even compile, and just concentrate on its text”&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Rather than worrying about &lt;em&gt;how&lt;/em&gt; the code will work at this point, &lt;strong&gt;concentrate on the behaviour, particularly from the user’s point of view&lt;/strong&gt;. It’s essential you block out implementation detail from your head at this point in the process because you’re just trying to nail down exactly &lt;em&gt;what&lt;/em&gt; you want to achieve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;strong&gt;what and the how are two separate design activities&lt;/strong&gt; which are too often mixed up, which makes coherent decision-making more difficult than it needs to be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Focus on being precise and limited in scope&lt;/strong&gt;, this will help you uncover assumptions and help you keep focused.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;TDD is an iterative approach to development&lt;/strong&gt;. When you are writing your tests you should be mindful of how to keep the work moving with fast feedback loops and small positive steps.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Start from the top down for new features&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;TDD is focused on letting you design for the behaviour you precisely need, iteratively. When starting on a new area you need to identify a key, important behaviour and then aggressively cut scope.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there you want to take a “top down” approach, starting with an acceptance test (AT) that exercises the behaviour from the outside. This will act as a north-star for your efforts. All you should be focused on is making that test pass. This test will likely be failing for a while whilst you develop enough code to make it pass.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/pxTaYu4.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you have your AT set up you can then break into the TDD process to drive out enough units to make the AT pass. The trick is to not worry too much about design at this point, just get enough code to make the AT pass because at this point you’re still learning and exploring the problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Taking this first step is often bigger than you think, setting up web-servers, routing, configuration e.t.c, which is why keeping the scope of the work small is important. We want to make that first positive step on our blank canvas, have it backed by a passing AT so that we can then continue to iterate quickly and safely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/t5y5opw.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As you develop, listen to your tests, and they should give you signals to help you push your design in a better direction but again, anchored to the behaviour rather than our imagination.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Typically, your first “unit” that does the hard work to make the AT pass will grow too big to be comfortable, even for this small amount of behaviour. This is when you can start thinking about how to break the problem down and introduce new collaborators.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/UYqd7Cq.png&#34; alt=&#34;&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is where test-doubles are very useful because most of the complexity that lives internally within software doesn’t usually reside in implementation detail, but “between” the units and how they interact with each other.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;/*&#xA;The design &amp;quot;outside the braces&amp;quot; is what often has &#xA;the biggest impact on internal quality&#xA;*/&#xA;&#xA;func NewStockCheckHandler(&#xA;    stockChecker StockChecker, &#xA;    productStore ProductStore,&#xA;) http.Handler {&#xA;&#xA;/* &#xA;implementation detail inside the braces is usually &#xA;low thrills and simple to test&#xA;*/&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can use test-doubles to explore the interactions between our collaborators with a much tighter feedback loop than if we tried to design and develop units isolated and then integrate them later.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For further iterations we may not need to write a new AT, we can simply add new behaviours to our existing units at a faster pace than the first one. We’ve made our first step, and we’re confident that we’re not developing them blindly because the units are integrated with the rest of the system.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;On “TDD-ing a design”&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Too often people assert that TDD is only compatible with a “bottom-up” approach where you imagine a bunch of abstractions up-front and then you “TDD them”.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is called “TDD-ing a design”. You’re not using TDD as a design method, merely a way of writing tests around some code. This often results in classes or functions being overly developed in isolation for extended periods and then only when you try to integrate them into the system and use them you realise the design is wrong.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the point where people declare TDD to be a poor design tool when in practice, they already had a design in their head and just added a very long feedback loop to it, exhaustively testing code and various edge-cases before &lt;em&gt;using it in their actual system&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that TDD demands we start with a test for a desired &lt;em&gt;behaviour,&lt;/em&gt; not a &lt;em&gt;design&lt;/em&gt;. This is very much “top down” development. When done correctly you stop “over-designing” and you write and design the code you actually need.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By TDD-ing a design you can fall into the trap of tests being tightly coupled to implementation rather than behaviour. This becomes extremely problematic when you want to change your implementation detail and your tests will become a burden. &lt;a href=&#34;https://quii.dev/The_Tests_Talk&#34;&gt;I talk about this in detail in “The Tests Talk”.&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Listen to your tests&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you follow the TDD process well you should end up with modular, loosely coupled, cohesive units within your system. This journey is rarely smooth. As requirements and knowledge changes your design will have to evolve with it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Tests can offer you a &lt;em&gt;focused lens&lt;/em&gt; into areas in your system where you can view the impact of your design isolated, which makes it far easier to appraise. &lt;strong&gt;Tests reflect your design back at you&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here are some common test smells to look out for. Commit them to memory, and you’ll be able to raise some interesting questions about your design to answer.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;High number of test-doubles (mocks), complicated setup&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;This is telling you that the unit under test has to collaborate with many things, this pain in your test world will be multiplied in all the cases you want to use this unit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This pain can sometimes feel hidden in the “real” usages but comes apparent when you start to change things and feel the pain of the tight and inappropriate coupling. You should be asking yourself why this unit has to collaborate with so many other things.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It points to leaky abstractions which could be remedied by:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Look at the test doubles. Are you having to mock out lots of methods? Perhaps you can consolidate this interaction into another more cohesive unit&lt;/li&gt;&#xA;&lt;li&gt;Maybe the unit itself has too many, unrelated behaviours. See if you can come up with a more cohesive design.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;Unclear intent&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Does your test &lt;em&gt;really&lt;/em&gt; explain the code’s behaviour and why?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;GOOS:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A test called testBidAccepted() tells us what it does, but not what it’s for.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If the test is unclear it could mean the responsibilities of the unit being tested is unclear and warrants a redesign.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Wide scope&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;This points to a lack of focus. Perhaps you need to break the problem down in to smaller parts.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Value the quality of your tests&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Start being more attentive about the quality of your test code. This will result in you writing tests that are cheaper to maintain and will challenge you to write more focused, modular code resulting a better designed system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Writing high-quality tests is cheaper than maintaining poorly written ones&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In a high-performing team where it must respond to client needs quickly and cheaply, good tests will enable them to have a productive experience. The opposite is also true.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Write the tests you want to see&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The easiest, most generic feedback I give to my colleagues is asking them to explain their tests out-loud. Often it’s harder than they imagine, even when the tests appear terse; and then an interesting conversation about the design almost always follows.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Reflect on the tests you have now. Do they express the intent of the behaviour well? Do they describe the &lt;em&gt;why&lt;/em&gt; clearly? If not, what would it take? Is it a simple refactoring of your tests or does it require some redesign?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Be attentive when you watch the test fail&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Be sure it fails the way you expect and that it fails with a clear message. If you skip this step you may be glossing over design decisions, or perhaps you don’t understand the requirements clearly enough.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Usually making the test fails “nicely” is a multi-step process, but it’s important to go through the steps until you get a satisfactory failure message due to your code not exhibiting the failure you need.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;View being in “the red” as something to get out of as soon as possible&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You should be running your unit tests extremely frequently, which is why it’s important they run quickly and don’t depend on slow things like the network or file-system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If at any point your tests are failing (so you’re in the red), you should be thinking about the shortest path to get back to “green”.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Often the safest way to do this is to revert your changes. By working in small increments this should never feel like a big deal.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is forbidden to refactor or redesign code in the red state because your feedback loop as to whether the changes are valid is broken.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Commit your work frequently&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;To be able to use your tests to help you guide your design they need to be green, but it’s inevitable that sometimes you’ll go down the wrong path and want to get back to safety. It’s therefore critical that you practice good source control practices and commit your work frequently.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I usually commit my work once I’ve made the test pass and that means if I get into a bad state during refactoring I can easily get back to working software again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So much of applying TDD is working in small, safe steps, so your mind is freer to think about the design of your system rather than juggling multiple concerns at once.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Refactor aggressively when in the green&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Most of the time your system should be in a state when you can refactor freely.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ill-factored code is problematic because it becomes hard to understand, which makes it harder to re-design. The process of refactoring in general will reveal improvements in the design for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Read Martin Fowler’s refactoring book and get in to the habit of applying common refactors. A lot of code I observe is not well-factored, but the good news is it’s a relatively easy skill to learn and once you’re proficient takes a matter of seconds or minutes to perform; in particular with help from your IDE.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you don’t practice TDD, what is your method for designing software? You do you! Can you describe your method to someone else, so they can follow a similar approach? It’s healthy to retrospect on how you work, to see if there are ways to improve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;No matter your design method, internal quality is essential for the productivity of your team. So many systems suffer from poor productivity and high costs because some developers and teams will neglect internal quality. It’s a false-economy to ignore internal quality and the pace at which you will be able to affect the external quality of the system will decrease quickly if you do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is of course possible to have software with high internal quality without practicing TDD, but I am not especially clever and want an easy life.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I design up front:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;it’s often wrong&lt;/li&gt;&#xA;&lt;li&gt;I have to think about too many things at once&lt;/li&gt;&#xA;&lt;li&gt;I design for things I don’t need&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;TDD offers a methodical, incremental way of designing code which feels like a simpler, more evidence-based way of creating useful, malleable software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Stick to the simple TDD process, listen to your tests and practice. This should result in you designing software, verified against concrete desired behaviours; rather than your imagination.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 28 May 2021 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>My experience of Introducing a team to Go</title>
      <link>https://quii.dev/My_experience_of_Introducing_a_team_to_Go</link>
      <description>&lt;p&gt;I was lucky enough to be invited on to the &lt;a href=&#34;https://changelog.com/gotime/151&#34;&gt;Go Time podcast to talk about Introducing your team to Go&lt;/a&gt;. It was my first time on a podcast and whilst I was a bit nervous and waffled a little, it was a lot of fun because &lt;a href=&#34;https://twitter.com/joncalhoun&#34;&gt;Jon&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/matryer&#34;&gt;Mat&lt;/a&gt; made me feel very welcome and comfortable.&lt;/p&gt;&#xA;&#xA;&lt;hr /&gt;&#xA;&#xA;&lt;p&gt;Introducing a new technology to an organisation is not only about technical merit. Even if it were, we’re all terrible objective judges of how good or bad programming languages are.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Change represents opportunity but also risk and if you want to succeed you need to build trust and consensus.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This requires you to find and influence the right people so you can get help, act with empathy to understand the concerns of a diverse range of roles and people, and work hard to bring people on the journey.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Background&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Around 4 years ago I joined a new company. Before I joined they had experimented with a few technologies and then seemed to settle on writing everything in JavaScript.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I’m very keen on Go and felt it would be a far simpler and more effective tool for a number of problems that we had to face. What follows is my story around bringing Go into the company, what worked, and what didn’t.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Bringing it up, badly&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A few months in to my new job we were starting a new project so we were in an inception. An inception is where various stakeholders and disciplines around building products get together to try and figure out on a high-level what we’re going to build and discuss a little how.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;During the architectural session I sensed an opportunity to stick my oar in and suggest Go for one of the systems that was being proposed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This was shut down, very firmly by a project manager. Paraphrased:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;We write JavaScript here. Using the same languages and tools lets us be efficient. We spent a lot of time experimenting with languages and now we have to focus. We won’t be using any new languages.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;At the time I did not take this well. I bit my tongue but inside I was thinking&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Who is this PM to decide how we should write software? Stay in your lane. I know I’m right here.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;In truth, it was poor judgement on my part to bring it up. It wasn’t the right forum as many people would just see this as me being technically frivolous and I didn’t think hard enough about the motivations of the people around me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;PMs are incentivised and judged on how effectively they deliver projects. They will of course be very conservative and resistant to anything that would add risk to a project.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt; Lessons learned&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Be aware of the room&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do you &lt;em&gt;need&lt;/em&gt; to bring up contentious subjects up with all of these people? Do you think it’s likely that people will agree?&lt;/li&gt;&#xA;&lt;li&gt;Think about the motivations of the people you’re talking to and tailor your message accordingly.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Chatting with the right people&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Hopefully you’re not naive to think that you can merely suggest an unfamiliar language and everyone jumps on board. If one of my engineers said to me&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Hey CJ can we write this in OCaml ?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It would be pretty irresponsible for me to go&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Why yes, let’s go for it. More fodder for my CV!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You need to build &lt;strong&gt;confidence&lt;/strong&gt; within your organisation that you’re not going to build some systems that only a couple of people are able or willing to maintain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’ll also need a  &lt;strong&gt;critical mass of people&lt;/strong&gt; who are skilled and enthusiastic about the language, with some real working software already running on your platform to prove it’s viable to work with.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Influence the right people&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you’re the only one pushing an idea you’re likely to fail. You’ll need to get to know your colleagues, try and identify the ones that are able to hold a captive audience and influence people. If you can convince the energetic influencers half the battle is won and you’ll have other people to help you.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Speak positively about Go, rather than criticising whatever is used now&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It’s not productive to harshly judge the current tools. At best you’ll get agreement but at worse you’ll&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Insult previous decisions made, which is especially bad when you’re unlikely to understand the context behind them.&lt;/li&gt;&#xA;&lt;li&gt;Alienate yourself from people who &lt;em&gt;do&lt;/em&gt; like whatever it is you’re criticising.&lt;/li&gt;&#xA;&lt;li&gt;Come off as a jerk and get into pointless arguments.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you like Go so much, it should be enough to speak positively about it but try to be realistic about it. Yes, Go does have downsides and it isn’t going to make your company 10x more productive overnight, don’t insult the intelligence of the people you’re talking to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To influence you need to &lt;strong&gt;act with empathy&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;You won’t convince everyone&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Often developers can be inflexible about their favoured tools. Don’t waste too much time on these scenarios because they are a path to negativity and conflict. Usually there’s enough space for some people who like X and people who like Y.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Getting organisational confidence&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Hopefully you’ve got a number of people with at least some interest in Go and perhaps 2 or 3 people who you can rely on to help you push forward.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Whoever is in charge should be thinking about the following when looking to adopt a new tool&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do my engineers want to write it?&lt;/li&gt;&#xA;&lt;li&gt;Are they able to write good, production-ready systems that they are happy to support?&lt;/li&gt;&#xA;&lt;li&gt;Does it fit into our existing infrastructure and tooling?&lt;/li&gt;&#xA;&lt;li&gt;Can we hire for it?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;How did we address these concerns?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; Book club, and learning at people’s pace&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We thought we could tackle this lunch &amp;amp; learn style where once a week we had our lunch in a meeting room and invite people to learn some Go.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We started by reading through &lt;a href=&#34;https://www.gopl.io/&#34;&gt;The Go Programming Language&lt;/a&gt; as a group. We hoped to learn a concept together and then set a “homework” of completing some exercises at the end of each chapter.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What actually happened, and what was learned&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We had a diverse group, it ranged from engineers with over 10 years experience to only just out of a bootcamp. One major stumbling block was the idea of using a statically typed language. A number of our engineers had only ever worked with Ruby and JavaScript so this was quite a strange thing to get over at first.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can demonstrate the strengths of static typing quite easily by showing how it stops you passing a &lt;code&gt;string&lt;/code&gt; to a function that requires an &lt;code&gt;int&lt;/code&gt;. I also related production issues we had with our JavaScript code which would be impossible in Go. It is an act of faith though, if you haven’t got a lot of experience building larger systems it feels like needless ceremony.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The trouble you may run in to is you &lt;em&gt;have&lt;/em&gt; to go at a pace everyone can work with. This may frustrate more experienced developers. They may have a temptation to dominate the group and show-off somewhat which leads to others feeling lost and lose confidence. Try to remind them that the goal of the group is for everyone to get up to speed with the programming language and &lt;strong&gt;this is an opportunity to practice their coaching and mentoring skills&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Only a few people would do the homework which at the time felt frustrating but what you need to understand is&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;People have lives. Not everyone can commit time to homework outside of office hours, especially parents.&lt;/li&gt;&#xA;&lt;li&gt;Some people want/need to be guided along in a more hands-on fashion&lt;/li&gt;&#xA;&lt;li&gt;Some people just aren’t &lt;em&gt;as&lt;/em&gt; enthusiastic as you. That doesn’t mean your efforts are doomed to failure! Just accept this.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Go by example&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The book approach wasn’t really working for the group so we thought we’d scrap homework and the quite detailed book in favour of studying &lt;a href=&#34;https://gobyexample.com/&#34;&gt;Go By Example&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We’d work through each page, discussing each small concept in detail and playing around with the code in the Go playground to try to understand the inner-workings better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Any temptation of seniors trying to show-off and skip-ahead were stamped out.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;We’re studying for-loops right now, not channels. We’ll get to that later.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Studying a small part of the language as a group without other distractions worked really well for us. They were comfortable bite-sized chunks that the less experienced could get a hold of, but the seniors could also have a bit of time to explore the topic a little more deeply to understand it better.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Making it more concrete&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Whilst the lunchtime club got people more excited about Go and starting to understand how to write it we had other activities to support out goal.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Dedicated Slack channel&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This was somewhere to post interesting links, share code, articles etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Developers would also show little Go projects they were working on to get feedback and ideas on what they’re working on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This helped foster the little mini-community that was forming and as the numbers grew the legitimacy of the idea increased.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Group activity&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Most of our work broadly fit into 3 categories&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Building fancy, interactive websites&lt;/li&gt;&#xA;&lt;li&gt;Building web servers which mostly call N APIs to get data, do something useful and put that data somewhere else (e.g a database) or make it available over HTTP&lt;/li&gt;&#xA;&lt;li&gt;Churn some data from a message queue&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;What I did was designed an exercise to showcase Go’s strengths in building robust, high-performing web-servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The exercise involves building a web server which takes a request containing N URLs (e.g http://quii.dev, http://news.bbc.co.uk). The server should respond with a “stitched” response of the two websites response bodies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The caveats I added to this were you were not allowed to have the WiFi on to complete this exercise, which forces the developer to&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use the built-in documentation&lt;/li&gt;&#xA;&lt;li&gt;Use the standard library&lt;/li&gt;&#xA;&lt;li&gt;Use &lt;code&gt;httptest&lt;/code&gt; to test the needed functionality (you wouldn’t be able to make a passing test that went to a real website)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The group was really successful in implementing it. The lesser experienced devs could make the required functionality, and the more senior ones could make the exercise more interesting by making the HTTP calls concurrent.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I feel this exercised showed the developers that&#xA;- They are capable Go developers&#xA;- They can do more than FizzBuzz, they can do their jobs in this language&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;10% time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We were lucky enough to have 10% time when every other week we could work on whatever we liked. Naturally a number of us would spend time reading more tutorials and starting to build web servers to do useful things.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I felt like we reached a real tipping point when we had a “Hello, world” server building and deploying through our Jenkins pipeline and deployed to live. This required us to work a bit on the companies’ tooling but finally we could point at something real.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Opportunism&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This process was never going to be done in a few weeks but after a few months of 10% time, exercises, prototypes and lunch &amp;amp; learns I felt we were at a point we could build something real, but what?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In truth a lot of the time writing a web server in Node or Go isn’t going to be radically different in terms of developer productivity or even performance. There’s so many things that influence these things and programming language usually isn’t the highest one.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was working on a system which had a micro-services approach to it. It would process thousands of messages from a message broker and for the most part Node was standing up quite well.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However, we started writing a part of the system which was very CPU bound, crunching a number of strings to build new strings. Node can struggle with CPU bound tasks, and it did for us. Our systems are horizontally scalable, so we went from 3 instances to 10 and increased the memory each needed to 512mb but it still struggled.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We had a pair of engineers spending a few weeks picking at low hanging fruit and trying different approaches to improve performance but it just wasn’t happening&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Pitching it&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I felt this was the right time for us to try re-writing this one service in Go. I spoke to the tech lead and chief architect and outlined the following&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Go should have much better performance in these kinds of tasks&lt;/li&gt;&#xA;&lt;li&gt;We have invested a lot of effort in getting a pool of enthusiastic developers who want to write Go&lt;/li&gt;&#xA;&lt;li&gt;Writing code isn’t the hard part here. Understanding the requirements is the hard part and we now have them codified for us to work from. I believed it wouldn’t take long to do properly&lt;/li&gt;&#xA;&lt;li&gt;We had technology-agnostic black-box-tests that we could run against the new version of the service to verify it&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;The result&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;As much as we attempted to practice with “real world” exercises as part of our learning, writing real systems is always different and things come up. It wasn’t the smoothest ride but we replaced the Node service with the Go one in around 2 weeks.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;It was around 10 times faster than the Node service, with only 3 instances using 256mb of memory&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When we deployed it, I thought we had made some kind of mistake as I just couldn’t believe the metrics I was seeing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Around 4 years later I asked my colleague how the system has held up and he said it has become a very resilient part of the system, now handling double the load it had when we originally made it with very few problems.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The kudos&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Presenting our accomplishments to the rest of the development team and CTO was a real highlight of my career. It felt like I had stuck my neck-out a bit and worked hard and this was the pay-off.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you’re thinking about introducing Go to a company, just remember that while programming languages are fun, they are a means to an end. Think about those ends and how you could get recognised for meeting them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our bosses shouldn’t care what programming language we use. &lt;strong&gt;Managers care about how we delivered useful software, smashed our performance targets, reduced our AWS bill and had fun&lt;/strong&gt;. Think about what you’re &lt;em&gt;really&lt;/em&gt; trying to achieve and use that to motivate your efforts.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; Go specifics&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Almost everything I’ve written here is not Go specific. You could take the same approach if you wish to introduce any language to your organisation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go does have some particular strengths that you can use to persuade people to use it&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Backward compatibility&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In enterprise this is especially important. Upgrading a codebase from Scala 2.8 to 2.10 was one of the most tedious activities in my career. Upgrading Go versions is just a configuration change.&lt;/li&gt;&#xA;&lt;li&gt;It means tutorials written 10 years ago are still relevant and correct today and this is one of the reasons it’s an easy language to pick up.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Stripped back, simple language&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In a previous life I was a Scala developer and the amount of bike shedding around approaches is incredible. You may find yourself frustrated at writing &lt;code&gt;for&lt;/code&gt; loops but soon you’ll realise how liberating it is to have only one way to iterate over a collection of things and do stuff.&lt;/li&gt;&#xA;&lt;li&gt;Much less to learn&lt;/li&gt;&#xA;&lt;li&gt;Much less to read&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Built for software engineering&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;All the things you learn about writing software to a high standard in a team environment, not a 1 person project that only works on one laptop is well catered for with Go.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Built in testing&lt;/li&gt;&#xA;&lt;li&gt;Built in benchmarking&lt;/li&gt;&#xA;&lt;li&gt;Easy to document code in a consistent manner with runnable examples&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;go fmt&lt;/code&gt; for consistent readability&lt;/li&gt;&#xA;&lt;li&gt;Compile to practically any platform you’d want to use and extremely easy to deploy&lt;/li&gt;&#xA;&lt;li&gt;Fast compilation time for excellent feedback loops&lt;/li&gt;&#xA;&lt;li&gt;Excellent IDE support&lt;/li&gt;&#xA;&lt;li&gt;Stable and rich standard library&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Trying to advocate for something new that you feel strongly about can be difficult and stressful. Work hard on your people skills to win-over helpful allies and build trust in your idea.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think of it as a marathon, not a sprint and keep retrospecting over the course of the journey. As I’ve said context is so important and only you can figure out what exactly is right for your own situation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that &lt;strong&gt;programming languages are not a goal in themselves, they are a means to an end&lt;/strong&gt;. If you’re thinking about championing Go in your job, try to &lt;strong&gt;put on your bosses hat&lt;/strong&gt; and think about what she’s trying to achieve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;It’s unlikely she&#39;s judged on what programming language is used&lt;/strong&gt;, it’s more likely to be things like whether they’ve delivered a good product, improved uptime or other things like that. If you can &lt;strong&gt;then relate Go to how those goals can be achieved&lt;/strong&gt; you’ll have a better chance of convincing people.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People will respect you for sticking your neck out and standing by your principles so long as you do it in a mature and respectful manner.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 16 Oct 2020 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>How my website works</title>
      <link>https://quii.dev/How_my_website_works</link>
      <description>&lt;p&gt;I recently redesigned this website. It’s not exactly a technical marvel, but I feel that is its strength, and I wish more projects I observed prioritised delivering useful content rather than expensive to implement designs. &lt;a href=&#34;https://quii.dev/The_Web_I_Want&#34;&gt;Most people just want to read some text and look at some pictures&lt;/a&gt; and it’s extremely easy to do this if you don’t tie yourself up in flavour-of-the-month technologies.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the way I got a chance to brush up on some of the more modern CSS techniques which was a lot of fun. People who complain about modern-day web development don’t know how lucky they’ve got it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There’s so many fantastic techniques and tools built into web browsers compared to 10 years ago that don’t require a lick of JavaScript.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The approach&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Under-the-hood not much has changed.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The server has a &lt;code&gt;posts&lt;/code&gt; folder which contains markdown files for each post.&lt;/li&gt;&#xA;&lt;li&gt;The web server is written in Go. When it starts up it opens up every markdown file, converts it into HTML and puts it in an in-memory map.&lt;/li&gt;&#xA;&lt;li&gt;When it gets requests, the server simply looks at the path and matches it to a key in the map of posts, returning the pre-rendered post.&lt;/li&gt;&#xA;&lt;li&gt;The frontend is plain HTML and CSS because it’s the best, simplest, most performant way of delivering textual content to users.&lt;/li&gt;&#xA;&lt;li&gt;It is deployed to Heroku and sits behind CloudFlare CDN.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I’ll use the simplest tools I can to deliver a good experience. This will sometimes rely on using CSS techniques that won’t work on older browsers. This is fine so long as my content is still accessible and looks &lt;em&gt;ok&lt;/em&gt;. This is called &amp;quot;graceful degradation&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation&#34;&gt;Graceful degradation is a design philosophy that centers around trying to build a modern web site/application that will work in the newest browsers, but falls back to an experience that while not as good still delivers essential content and functionality in older browsers.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2&gt;New things I learned&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties&#34;&gt;CSS Variables&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;On the face of it they seem like a nice way to DRY up some code and give some semantics to things like colours.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;:root {&#xA;    --nav-colour: hsla(354, 100%, 71%, 1);&#xA;    --link-colour: hsl(354, 100%, 71%);&#xA;    --bg-colour: hsla(30, 100%, 99%, 1);&#xA;    --code-colour: hsla(327, 24%, 35%, 1);&#xA;    --text-colour: hsla(280, 12%, 20%, 1);&#xA;    --header-colour: hsla(280, 12%, 20%, 1);&#xA;&#xA;    --font-size: 2.2rem;&#xA;    --line-height-multiplier: 1.5;&#xA;}&#xA;&#xA;time {&#xA;    color: var(--code-colour);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I think they’re an interesting way of identifying the complexity of your design. If you give yourself the constraint that the only place you’re allowed to declare a colour value is within your variables then you’ll have a well-organised list of colours on your website. If that list gets long, or it becomes hard to name your variables ask yourself&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Do I really need all these colours for my website?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;You can take the same line of thinking in respect to the variables you use with your typography and your general spacing. By using variables it forces you to &lt;strong&gt;think&lt;/strong&gt; and will help give your design a more consistent and less cluttered feel.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme&#34;&gt;Media query for dark mode&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Dark-mode feels pretty faddy to me but I am pleased there is a nice progressive way to change the style of your website without relying on any wonky JavaScript.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If supported, my website will automatically change into dark-mode with no prompting from the user. In OS X you can set dark mode to automatic which will go from light mode to dark through the day, and my website will respect the user’s wish.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/mwvLVrg.png&#34; alt=&#34;Dark &amp;amp; light mode in OS X&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This feels much better than expecting users to have to update some kind of setting on every website they visit.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This works especially well with CSS variables. To enable dark-mode all I had to do was change the value of my variables.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@media (prefers-color-scheme: dark) {&#xA;    :root {&#xA;        --nav-colour: #15B097;&#xA;        --link-colour: #3282b8;&#xA;        --bg-colour: #051923;&#xA;        --code-colour: #15B097;&#xA;        --text-colour: #EDF6F9;&#xA;        --header-colour: #1C77C3;&#xA;    }&#xA;&#xA;    img {&#xA;        filter: brightness(.8) contrast(1.2);&#xA;    }&#xA;&#xA;    body {&#xA;        font-weight: 350;&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Easy!&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Fallback for older browsers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Without any effort, my website is still useable for users of Internet Explorer (and probably Netscape Navigator).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/FsuA3eZ.jpg&#34; alt=&#34;IE11 without any fallback&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Web browsers are very forgiving and will do their best effort to render even if they see syntax they don’t understand. As I am relying on robust, battle-tested technology (HTML &amp;amp; CSS) it &amp;quot;works&amp;quot; - the content is still accessible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I had done some react-whizz-bang framework single page app I would have to jump through a lot more hoops to reliably deliver some text.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Fallback techniques&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Including this in the head of the document means this CSS file will only be loaded by users of IE9 and older.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;!--[if lte 9]&amp;gt;&#xA;    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;/static/fallback.css&amp;quot;&amp;gt;&#xA;&amp;lt;![endif]--&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The following media query lets me style for IE10 and IE11&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {&#xA;    body {&#xA;        /* IE 10 &amp;amp; 11 specific style declarations */&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;I don’t anticipate many users of IE11 or under being especially interested in a programmer’s blog, but it can’t hurt to help them out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/MAfD5nk.png&#34; alt=&#34;the website in IE11&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s not pixel-perfect, but it doesn&#39;t have to be. I have seen teams spend &lt;em&gt;days&lt;/em&gt; fixing minor pedantic styling issues with Internet Explorer and I can&#39;t imagine that&#39;s the best way to spend expensive developer time. Are you building websites to satisfy your users or designers?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Performance&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/FsvfvBh.png&#34; alt=&#34;Screenshot of assets downloaded for the website&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;All the content delivered and styled in 40ms with under 5kb of payload&lt;/strong&gt;&#xA;&lt;i&gt;(excluding post-specific images, which I try to minimise)&lt;/i&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;All these fancy computers we use have an impact on the environment. By taking a minimalist approach my website&#39;s carbon footprint is &lt;a href=&#34;https://www.websitecarbon.com/website/www-quii-dev/&#34;&gt;cleaner than 99% of the websites tested on websitecarbon.com&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Big deal Chris, it’s only HTML and CSS, it’s not a real website&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Yeah, it’s only HTML and CSS, brilliant isn’t it. Easy to make, accessible and performant. I made my first website around 21 years ago, and I find it quite comforting the same technology I worked with then works now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I wish more websites were written like this rather than clogging my network and computer with megabytes of useless JavaScript written by developers running transpilers over transpilers on frameworks built on top of other frameworks and for what?&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fancy transitions?&lt;/li&gt;&#xA;&lt;li&gt;The client not doing a full page refresh going between pages?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Do your users actually care about this? Click between links on my archive page and tell me it’s too slow and has a bad user experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are projects where SPAs are a good fit, but many developers are poor at making this decision and add a huge amount of complexity for no real reason.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Making a static website does not require a fancy blog generator built on top of a gig of &lt;code&gt;node_modules&lt;/code&gt;. &lt;strong&gt;You do not need special tools to make a great website.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even if you’re not a confident “backend” developer you don&#39;t &lt;em&gt;have to write a web server&lt;/em&gt; like I did; you can still… create websites with plain old HTML files, written by hand!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a totally legitimate way of making many kinds of websites and will most likely result in the best user experience for the least effort.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 27 Aug 2020 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Start naming your test doubles correctly</title>
      <link>https://quii.dev/Start_naming_your_test_doubles_correctly</link>
      <description>&lt;p&gt;A lot of developers are very vague when they name their test doubles which makes tests needlessly more difficult to understand.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In conversation there’s also often ambiguities which cause problems. I overheard on a podcast:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Have you ever used a mock where you make assertions on the call?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This post will hopefully illuminate why that sentence is a bit silly. By making a little more effort to be precise with your naming, you can communicate the intent of your tests and the design of your system more effectively&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Quick primer on dependencies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To separate concerns, we often make objects that will “depend” on other objects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We “inject” or “pass in” these dependencies when we construct them, so they can do a job. This is called &lt;em&gt;Dependency Injection&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A &lt;code&gt;ShoppingCart&lt;/code&gt; sends an email when you call its &lt;code&gt;sendOrder&lt;/code&gt; method.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We don’t want &lt;code&gt;ShoppingCart&lt;/code&gt; to have to know &lt;em&gt;how&lt;/em&gt; to send emails as well as everything else so we give it an &lt;code&gt;Emailer&lt;/code&gt; when we create it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;new ShoppingCart(new MailgunEmailer())&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can then use the emailer without having to know &lt;em&gt;how&lt;/em&gt; emails are sent, and you have your separation of concerns.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;sendOrder() {&#xA;    // interesting domain logic&#xA;    this.emailer.send(confirmation)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This approach has implications for our tests. With tests, we prefer not to use real objects for dependencies because we want to be able to control them, so we use something different:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It would not be desirable to send a real email every time a test is run.&lt;/li&gt;&#xA;&lt;li&gt;We sometimes depend on things that are slow, but we like our tests to be fast because feedback loops are extremely important&lt;/li&gt;&#xA;&lt;li&gt;It would be hard for us to exercise failure scenarios using real dependencies. How do you get a 3rd party email service to deliberately fail?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Use “Test Doubles”&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Not&lt;/em&gt; specifically mocks&lt;/strong&gt;. A test double is what you inject into an &amp;quot;object under test&amp;quot; (OUT) to control a dependency; Like a stunt double!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using the precise words for test doubles helps reveal intent and documents your design more effectively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s not about being big and clever, it helps you communicate unambiguously. Software development is a team-sport so clear communication will help your team work better.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The different kinds of test doubles&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Dummies&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes you have arguments to functions that you don’t care about. Dummies are the arguments you pass in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;const dummyLogger = jest.fn()&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Stubs&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Some objects will &lt;em&gt;query&lt;/em&gt; dependencies for data.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Stub&lt;/em&gt; the dependency&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;const stubUserService = jest.fn(() =&amp;gt; &#39;Miss Jones&#39;)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Spies&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Sometimes you want to call a method (or more abstractly &lt;em&gt;send a command&lt;/em&gt;) to a dependency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can be hard to tell in a test this happened from the outside as it’s an internal detail.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to verify these commands, use a &lt;em&gt;spy&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;const spyEmailSender = jest.fn()&#xA;// do some stuff&#xA;expect(spyEmailSender.mock.calls.length).toBe(1)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3&gt;Fakes&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Usually a “real” implementation but constrained.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like an in-memory database.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Not as popular anymore due to things like Docker which let you spin up local versions of databases without the risk of there being differences between a fake and a real implementation.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Mocks&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Mocks are a &lt;em&gt;kind&lt;/em&gt; of test double! Mocks are precise and encapsulate the detail of your interactions more explicitly. You describe upfront what calls you expect on your test double&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Order&lt;/li&gt;&#xA;&lt;li&gt;Arguments&lt;/li&gt;&#xA;&lt;li&gt;Specific return values&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If the object under test doesn’t call things as expected the mock will error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So returning to&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Have you ever used a mock where you make assertions on the call?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;What is being described is just &lt;em&gt;a mock&lt;/em&gt;. If you&#39;re not worried about the calls, you&#39;re talking about a &lt;em&gt;stub&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Why “mocking too much is bad”&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The risk is your tests become needlessly precise and coupled to implementation detail. This is also true of spies as they have a similar nature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&#39;re overly specific with your mocks, when you want to refactor things you may find tests failing for annoying reasons that have nothing to do with &lt;em&gt;behaviour&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Why “having too many test doubles is bad”&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Listen to your tests if they cause you pain. If you have many test doubles in a test &lt;strong&gt;that means your OUT has many dependencies&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Does that sound right to you? It shouldn’t and it means you probably need to take a look at your design.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;An anecdote&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yesterday I reviewed a test which had a test double named&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;getterFn&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I had to spend some time reading the test to understand what was going on, it turns out it should&#39;ve been called&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;spyCSVFetcher&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once this was ascertained it turned out the writer had actually neglected to spy on the number of calls, which was actually a core part of what was supposed to be tested.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the double had been named correctly in the first place (which is very little effort) I would know to look for assertions on the way it was called to help me understand what the intent of the code is. Instead, it took some investigation.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Consistently using the recognised names for test doubles will help you be precise when communicating with other developers. It&#39;s a low-effort way to improve the way you work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For instance if you name something a &lt;code&gt;dummy&lt;/code&gt; rather than a &lt;code&gt;mock&lt;/code&gt; the readers of your tests can forget about that particular test double and focus on the important collaborators.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Tests should act as documentation so describing your test doubles clearly will help reveal the design of the test for maintainers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;So start naming your test doubles correctly, today!&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Quiz&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What does a test with lots of doubles tell you?&lt;/li&gt;&#xA;&lt;li&gt;How do you improve the design of a test with many test doubles?&lt;/li&gt;&#xA;&lt;li&gt;Name all the kinds of test doubles&lt;/li&gt;&#xA;&lt;li&gt;How is a mock different from a spy?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Further reading&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://martinfowler.com/articles/mocksArentStubs.html&#34;&gt;Martin Fowler&#39;s post &amp;quot;Mocks aren&#39;t stubs&amp;quot;&lt;/a&gt; goes into this topic in great detail.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/dependency-injection&#34;&gt;Learn Go with tests: Dependency Injection&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 30 Jul 2020 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Work 2019</title>
      <link>https://quii.dev/Work_2019</link>
      <description>&lt;p&gt;This post is a summary of work stuff over the past year which covers my first adventures into&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Technical leadership and line-management&lt;/li&gt;&#xA;&lt;li&gt;Hiring and building a brand new team&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I think I&#39;ve helped build a pretty rad team, so if you&#39;re interested in that kind of thing, read on.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Rough start&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;After working in one of the most productive, interesting and fun teams I&#39;ve ever had the pleasure to be a part of, the team has to be disbanded due to complicated (and boring) politics.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We were given freedom to move in to almost any team within the organisation but I &lt;em&gt;really&lt;/em&gt; didn&#39;t take our team being disbanded well at all so I think in my eyes every opportunity looked boring and unfulfilling. It was never going to work out.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;New job&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Happily a new opportunity came about with my previous employer. I&#39;d worked there for just under 2 years; it was really enjoyable, I liked the environment and I&#39;m proud of the work we did and how we did it. It felt like we stood behind the good DevOps principles and it worked out well for us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This would be a different role though, I would be a technical lead. I have been a technical lead before but in a different environment and without the line management responsibility needed for this role.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was a little tentative about this at first. I hadn&#39;t been a line manager before and everyone I&#39;ve spoken to about it to implies it&#39;s horrible. My future boss spun it pretty well though:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I&#39;d get to hire my own team&lt;/li&gt;&#xA;&lt;li&gt;I&#39;d get to run it &lt;em&gt;more-or-less&lt;/em&gt; how I like (so long as we deliver, obviously).&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://quii.dev/How_to_go_fast&#34;&gt;He knows I have strong opinions about how teams should be run&lt;/a&gt; and is happy to give me the autonomy to try to make it happen.&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I deliberated on this and thought about leads who had worked well with me and those who hadn&#39;t. A couple of people who&#39;ve had the dubious pleasure of managing me have had a real positive effect on my career (and life, I suppose). They pushed me into things I never saw myself doing and gave me confidence to stand behind my convictions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I put all that together with someone giving me this rare opportunity to pay it forward and to help some people find the joy I get out of software-engineering; I had to give it a go. I may never get this kind of opportunity again!&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;My personal goal for this job&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Learn how to create great teams who not only deliver good software with minimal stress, and actually enjoy it.&lt;/li&gt;&#xA;&lt;li&gt;Grow some engineers&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Hiring&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The initial suggested makeup for my team was:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A senior&lt;/li&gt;&#xA;&lt;li&gt;A mid-level&lt;/li&gt;&#xA;&lt;li&gt;An associate (junior)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Now where I work isn&#39;t as glamorous as one of these fancy fin-tech startup whatevers, but it &lt;em&gt;is&lt;/em&gt; a good place to work. The environment is great, we&#39;re empowered and work in a pretty cutting edge way. We go to DevOps conferences and hear about best practices and we can honestly say we do a lot of them. We deploy many many times per day, deployment is a non-event for us.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Getting that across to the highly competitive London job market I guess is hard because I had to do &lt;em&gt;a lot&lt;/em&gt; of recruitment effort to eventually get the right people.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Diversity and all that&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I was determined not to hire 3-4 clones of myself. I am infuriating to work with. Studies show diverse teams have better results. Also, hiring diverse teams is the right thing to do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We approached &lt;a href=&#34;https://makers.tech/&#34;&gt;Makers Academy&lt;/a&gt; to help us hire as their raison d&#39;etre is bringing people from different backgrounds into software development. I&#39;ve had a very positive experience working with Makers graduates over the past 5 years, they&#39;ve always made the teams and people around them better so I wanted more of that.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It was a fun and intense experience of pitches, chatting to lots of people and interviewing a number of great candidates. If it were up to me we would&#39;ve hired more but in the end we hired 3 excellent developers who are thankfully nothing like me.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The team&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The stars aligned quite nicely in that after months of recruitment going nowhere my team of &lt;strong&gt;3 associates and a senior&lt;/strong&gt; more or less joined at the same time. It was super exciting to have a new team suddenly appear in the office.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Having a brand new team, and role suddenly land on my lap all at once was pretty intimidating at first but the people I hired made it a lot easier because they&#39;re all excellent people and I had good support from other people in the department.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How I tried to make it work&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before leaving Springer Nature I had a meeting with one of the managers which was more impactful than he probably realises. He said&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;You need to take learning management as seriously as you do learning software development. In the end you have a direct effect on people&#39;s lives&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;OK, it&#39;s a bit dramatic but it is true. I reflected on managers who hadn&#39;t worked for me and how frustrated and annoyed I was about the situation even outside of work.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s definitely a problem that a lot of people seem to think that management comes naturally to certain people and is not a skill to learn and practice.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So I picked up some books and watched some talks in the hope I could actually achieve my goals and not let my team down.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://www.amazon.co.uk/Phoenix-Project-DevOps-Helping-Business-ebook/dp/B00AZRBLHO&#34;&gt;The Phoenix Project&lt;/a&gt; &amp;amp; &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Machine_That_Changed_the_World_(book)&#34;&gt;The Machine That Changed The World&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;These are two books that talk about the problems you have when trying to build big complicated things with lots of people. They&#39;re very different books,&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Phoenix Project is described as a &amp;quot;DevOps Novel&amp;quot; which sounds lame as hell but is actually really enjoyable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Machine That Changed The World talks about the approaches to manufacturing cars. From artisan bespoke cars, to mass production and then lean manufacturing. It sounds far away from software development but as you read it you find yourself nodding along, drawing parallels with our industry.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There&#39;s &lt;em&gt;loads&lt;/em&gt; to take from them and here are the main bits I got:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Command and control definitely does not work. You need to empower the people who actually create things to make decisions as they&#39;re the people with the most up-to-date, relevant knowledge.&lt;/li&gt;&#xA;&lt;li&gt;You &lt;em&gt;must respect work in progress (WIP) limits&lt;/em&gt;. It&#39;s way better for a team to properly finish tasks and only work on a small number of things than hurriedly work through dozens of tasks. Disrespect of WIP &lt;em&gt;will&lt;/em&gt; slow you down.&lt;br /&gt;&lt;/li&gt;&#xA;&lt;li&gt;A better understanding of &amp;quot;lean&amp;quot;. Once you read these two books you have a very clear idea of where agile gets a lot of its ideas from.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I summarise these ideas in more detail in &lt;a href=&#34;https://quii.dev/The_ghost_of_Henry_Ford_is_ruining_your_development_team&#34;&gt;The ghost of Henry Ford is ruining your development team&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;&lt;a href=&#34;https://abookapart.com/products/resilient-management&#34;&gt;Resilient management&lt;/a&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is a very practical book on technical leadership, it&#39;s quite short and I have found it invaluable. It has given me concrete things to do to help build my team.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Growing people&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;It has some fascinating insights between the terms &amp;quot;coaching&amp;quot; and &amp;quot;mentoring&amp;quot; which I share with basically everyone because it really has changed the way I try to help people.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Mentoring&lt;/strong&gt; Giving advice and perspective to help someone solve a problem. Quite a direct way of giving information. Good for overcoming roadblocks. Focused on the &lt;em&gt;problem and solution&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Coaching&lt;/strong&gt; Asking open questions to explore a topic more. I like to see it as trying to help someone &amp;quot;join the dots&amp;quot; of an idea. This style will have a longer term impact on people and will help both parties explore ideas more.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Having these ideas explained has made me more conscious about how I try to help people solve problems. I find myself looking for coaching opportunities more when working with people and have tried to take that into our workshops by encouraging coaches to draw on real-life analogies to help explain technical ideas (&lt;a href=&#34;https://twitter.com/gypsydave5&#34;&gt;David Wickes&lt;/a&gt; is extremely good at this).&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Self reflection&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;The book discusses how when people go from engineering to leadership need to understand their &amp;quot;default work mode&amp;quot; and how it might not be compatible with different goals as a lead. I think my default work mode is &amp;quot;just fucking do it&amp;quot; and &amp;quot;ask for forgiveness, not permission&amp;quot;; this has broadly worked out quite well for me as an engineer in teams. However as a lead I need to check myself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Sometimes I just want to open my IDE and refactor some code I dont like and &lt;code&gt;git commit -am &amp;quot;refactor&amp;quot;&lt;/code&gt;. On a high level that is the right thing to do but how does that help my teammates in the long-run? I should see these things as a coaching opportunity and instead find time to bring it up with people and explore the space with them so that in future everyone else can see the problems in our code better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The book asks you what you think your management style is so you can reflect on it. Just asking that question of myself was weird and difficult, this is what I came up with:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;No micromanaging. Feel strongly about empowerment, ownership and trust. I have no interest in denying clever people the opportunity to use their skills to achieve our goals.&lt;/li&gt;&#xA;&lt;li&gt;Reliant on honest feedback, sometimes I don’t observe myself not being great&lt;/li&gt;&#xA;&lt;li&gt;Hope to focus more on growing people than “getting shit done” but I will need to check myself because that is my “default work mode”.&lt;/li&gt;&#xA;&lt;li&gt;Want to act as a sponsor, finding opportunities for people to grow&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I like to think that I&#39;ve stuck to my guns with this style and it seems to be working out OK.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Setting direction&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;The book also instructed me to write a vision (or North Star) for the team&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Be an amazing team that is continuously improving that ships well-engineered software with minimal hassle and stress by relying on craft and taking advantage of our autonomy to apply industry best practices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We will take pride in our actual agility to confidently change and evolve our software as and when we need to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we get good at creating great systems, our stakeholders will always be happy with us and will continue to give us autonomy.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;And a mission, which is a more grounded version of it&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Openly and honestly communicate with each other to guide ourselves so we can grow&lt;/li&gt;&#xA;&lt;li&gt;A culture of learning and sharing knowledge&lt;/li&gt;&#xA;&lt;li&gt;Confidence to suggest changes to improve our ways of working and our code&lt;/li&gt;&#xA;&lt;li&gt;Continuously tightening feedback loops to guide improvement&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;And a strategy to get there&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Finds ways to break problems down into smaller chunks so we’re never working on something that feels too intimidating. Perfect is the enemy of good, better to ship 80% of the feature quickly than 90% in 3 months time.&lt;/li&gt;&#xA;&lt;li&gt;Low WIP (work in progress) so we’re not spinning too many plates and that allows us to focus on small tasks that we can execute well.&lt;/li&gt;&#xA;&lt;li&gt;Culture of feedback. Practice saying something nice every day! Remember that giving someone “negative” feedback is an act of kindness (so long as it’s done kindly).&lt;/li&gt;&#xA;&lt;li&gt;Practice continuous integration. Both in respect to code and knowledge.&lt;/li&gt;&#xA;&lt;li&gt;Pairing, mobbing. Even if you work on a task by yourself it should be considered very unusual not to seek feedback on your work as you do it.&lt;/li&gt;&#xA;&lt;li&gt;Give ourselves time to research, in particular pre standup research times&lt;/li&gt;&#xA;&lt;li&gt;Share interesting things you learn.&lt;/li&gt;&#xA;&lt;li&gt;Ensure everyone has time to work on all aspects of our code and development practice, actively fight any silos of knowledge forming.&lt;/li&gt;&#xA;&lt;li&gt;Everyone on the team contributes in forming how we work.&lt;/li&gt;&#xA;&lt;li&gt;We should take pride in our work. If you’re not proud of something, we discuss how to make it better.&lt;/li&gt;&#xA;&lt;li&gt;Identify any single points of failure we may have in our ways of working and work to spread the knowledge &amp;amp; responsibility&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If nothing else it felt cathartic to write this down and I&#39;ve encouraged the team to contribute to the document.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I sometimes feel my role, &lt;em&gt;if anything&lt;/em&gt; is to keep pushing the team in the direction this describes so that we do become that team that I hope we will be.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;A talk from Makers&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A few of us went to a Leading a Diverse Team workshop at Makers. It was interesting and one talk resonated with me a lot. It discussed how often as a leader we project our own ideas as to how to accomplish a goal based on our own experiences. This is fine and well intentioned but it&#39;s from a position of bias and you may be unintentionally shutting out different ideas.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A better, more empowering way of trying to achieve what I&#39;m trying to achieve is setting a vision but then encouraging the individuals in my team to think about the unique ways &lt;em&gt;they&lt;/em&gt; can contribute toward that vision that I may not be thinking of.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;My&lt;/em&gt; way of achieving goals is one means to that end but it doesn&#39;t have to be the only one; and there&#39;s probably better ones that my team can think of based on their own background, skills and experience. It&#39;s my job to encourage people and build a great environment so they can explore their own ideas.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Lessons learned, things to improve&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Introvert Chris&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I am one of those introvert-ish people who can seem relatively outgoing most of the time but I definitely suffer from running out of social energy quite quickly and just wanting to get a break from people (no offence, team).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This role definitely has taken its toll on introvert Chris at times and I need to find ways of managing that better but I dont have many good ideas yet. I think perhaps now my team is settled more I shall try and delegate a few more meetings to people as it will save me some social energy and is an opportunity for others to contribute in those areas.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;You cant just mob&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I hear a lot of great things about mobbing and I am totally on-board but for whatever reason when we tried it did not go well. I suspect it was a function of the team being very unfamiliar with each other and the nature of the work (it was very new-project, infrastructure work).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Still, like leadership it&#39;s probably something you have to study and not just an innate skill. I hope to read more about this and try it again next year.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;General time management&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&#39;m not happy with the amount of time I&#39;ve got to pair with everyone. I&#39;d say I do it quite often but not enough. The times where I paired I&#39;ve been able to give much more useful feedback in our one-to-ones.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When the role was first offered to me it was proposed I would manage 3 people. That quickly turned to 5 and at the start of 2020 7. To serve all these people well I am definitely going to have to think carefully about what I am doing every day and try to find opportunities to delegate useful tasks that will help people grow and free my time up at the same time.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Study more&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The few books I got through gave me some excellent ideas and set me up well. I want to continue reading this subject to get better. I&#39;m currently reading &lt;a href=&#34;https://www.amazon.co.uk/Elegant-Puzzle-Systems-Engineering-Management-ebook/dp/B07QYCHJ7V&#34;&gt;An Elegant Puzzle&lt;/a&gt; which is very interesting but seems maybe better suited to a head of engineering role rather than the one I&#39;m in right now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next books will be:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.amazon.co.uk/Manager%60s-Path-Camille-Fournier/dp/1491973897&#34;&gt;The Manager&#39;s Path&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.amazon.co.uk/Thinking-Systems-Primer-Diana-Wright/dp/1844077268&#34;&gt;Thinking in Systems: A Primer&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Final reflections&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&#39;m glad I didn&#39;t try and &amp;quot;wing-it&amp;quot; with management. I&#39;m still learning though and there&#39;s lots of room for improvement but I &lt;em&gt;think&lt;/em&gt; the upfront study I did helped grease the wheels for my team and get it off to a good start.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;During hiring I was very upfront about what my expectations and aspirations for the team were which resulted in a group of people joining who seem to be bought into the idea and are contributing toward it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;m really pleased and proud of how things are going. I shouldn&#39;t take for granted that we managed to turn a group of strangers with various backgrounds and experiences into a great team. The culture is fun, open, curious and we take pride in our work; which is honestly exactly what I wanted.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I feel everyone has become better engineers since joining and I am confident we&#39;ll do great next year so long as we keep pushing ourselves to get better and better. (that felt like a bit of a lame manager-esque rallying call, sorry)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I think the most gratifying moment for me was a small one. A few weeks after the team formed I went on holiday. When I came back one of my team mates told me they had changed the process. I replied:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Good&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It&#39;s the team&#39;s process, not mine. I want them to be comfortable making decisions about how we work and voicing strong opinions about the way we do things, and this demonstrated we are heading in the right direction.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 28 Dec 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Gamifying Continuous Integration</title>
      <link>https://quii.dev/Gamifying_Continuous_Integration</link>
      <description>&lt;p&gt;If you read the internet, you&#39;ll soon realise that a large number of software developers don&#39;t understand what CI is and why it&#39;s important.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s important to state that &lt;strong&gt;continuous integration is not a server&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like the word DevOps, people seem to think these important principals of software engineering are about tools and products. Perhaps misinformed managers think if they buy the right magic box they can finally deliver their projects on time.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Continuous integration is &lt;em&gt;continuous integration&lt;/em&gt;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Read the words&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s about making sure that when you are working on code, it is the most up to date version of the entire team&#39;s code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have multiple versions of code checked out on different branches or machines, then you are &lt;strong&gt;not collectively &lt;em&gt;integrated&lt;/em&gt; in respect to code&lt;/strong&gt;. The code you see, is different to the code your colleague sees.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In an ideal world if you could somehow all work on same computer at the same time comfortably, that would be pure CI.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&#39;ve ever used VS-code&#39;s Live Share plugin, that&#39;s as pure a CI experience you can get in a remote environment. If you&#39;ve not used it, it allows you to connect to a colleague&#39;s VS code and edit the code together as if you&#39;re working on the same computer. The changes you make are reflected (or &lt;em&gt;integrated&lt;/em&gt;) to everyone else in the session - the feedback is immediate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A much simpler experience of CI is mobbing. Everyone is working from the same version of the code together.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How do you know if you&#39;re not practicing CI well?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;One obvious sign is developers wasting lots of time resolving large merge conflicts. Merge conflicts are a direct result of you working on a version of the code that isn&#39;t up to date. Your team are not integrating their changes &lt;em&gt;continuously&lt;/em&gt; and therefore as they make changes the risk of making invalid changes increases.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The time wasted on merge conflicts has compounding effects as it increases the delays of integrating your own changes to the system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;One might argue you can resolve this by structuring work differently to avoid conflicts, even going as far as to re-architect your &lt;em&gt;system&lt;/em&gt; to avoid merge conflicts. An often touted reason to go for microservices is it allows teams to work independently.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Reader, I have worked on a team with 20 odd developers, shipping frequently on a monolith and very rarely did we have merge conflicts. We also didn&#39;t do pull requests, we committed to the main branch.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;If you don&#39;t practice CI you are not working with your team as well as you could&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Changes to the system are invisibly stored on your colleague&#39;s computers where they are of no use to you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You could be imagining some great abstraction given the code in front of you but unfortunately the code in front of you is &lt;em&gt;not&lt;/em&gt; the source of truth because unknown to you another developer merges a gigantic change after spending a week on a feature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People become reluctant to refactor parts of the code because someone is working on a branch that is vaguely near the code you want to change so you wait a few days and then forget about it.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How do you CI well?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The simplest way is for everyone to commit to main (or master), frequently. It really is that simple!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To be good at continuous integration, you should continuously integrate your changes to main. That way everyone will be working with the same version of code for the most part.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s important that you respect your colleagues and run your tests before pushing. If the build is broken the team should &lt;em&gt;stop&lt;/em&gt; committing unless it&#39;s to directly fix the problem. If people keep committing whilst the build is broken it will become very difficult to diagnose what the problem is and the new commits may compound the issue.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The process, in full&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;git pull -r&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Make a positive change to the system&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git commit -am &amp;quot;added blockchain terraform machine-learning module 2.0&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git pull -r&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;./build.sh &amp;amp;&amp;amp; git push&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;This practice is simple to follow, doesn&#39;t require elaborate review systems, branch strategies etc, and forces good habits.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In order to push frequently, you need to pull changes frequently&lt;/li&gt;&#xA;&lt;li&gt;You can only push frequently if you work on small tasks, iteratively. There are many, many reasons why this is a wonderful, less risky and easier way of working. (see TDD, XP, any decent agile book, etc etc)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;It wont &lt;em&gt;entirely&lt;/em&gt; stop merge conflicts occurring, but they should be very infrequent and because you&#39;re doing small changes they&#39;re typically trivial to resolve.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;But what about code review?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The industry seems to have conflated reviewing code with a very specific, relatively new process of looking at code when a pull request is submitted; usually too late once all the code is written.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Did you know that you can talk about code, at any time during the day?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Did you also know that the correct abstractions and patterns may not be apparent when the code is &amp;quot;done&amp;quot; and you&#39;d be better off encouraging an environment where people are free to refactor code when they want to, rather than having to go through a laborious process every time they want to change the code. I&#39;ve worked on and observed projects that practice code review very strictly and yet the code is still not great.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Relying on a process of checking code before it is merged is not going to result in a healthy codebase alone.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With this way of working I strongly encourage pair programming because people rightly assert that as a lone developer it is very easy to do something wrong if you don&#39;t gather feedback. Pair programming facilitates a constant feedback loop on what you are writing.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What if someone commits something wrong/broken?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;First of all, no process in the world can prevent this. Stuff does go wrong, and you would be better asking yourself:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;How can we detect and recover from problems easier?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Secondly, this approach does require a healthy and collaborative team that talk to each other regularly about what they are working on. They should be talking to each other when they start a bit of work about what they are going to do, how they will release it safely, what kind of tests, etc. Couple that with working on small things iteratively the risk of pushing something catastrophic are very low.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If someone does push some code that maybe works (so the tests pass, monitoring is all good, etc) but is actually &amp;quot;bad&amp;quot;. Well so what? We can refactor it if we don&#39;t like it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What if I, a tech lead want to check every change before merging&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I don&#39;t want to work with gatekeepers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I want to work on a team that trusts one-another.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Perfect is the enemy of good.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;So is a system of pull requests bad?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Not at all, they&#39;re perfect for open source projects where you want to welcome contributions from other people but dont have implicit trust. In that case you will want to review changes that go into your precious project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For a team where you trust the developers all it adds is overhead.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Liberation&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We should be &lt;em&gt;removing&lt;/em&gt; the barriers to changing software, not adding walls and walls of bureaucracy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this kind of environment people fix code when they see it needs fixing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This way of working tightens feedback loops and increases actual meaningful agility.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;CI is not just about the code&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It&#39;s important to integrate knowledge of domain, work etc. (so important not to have silos of work with just the BAs/UXD etc)&lt;/li&gt;&#xA;&lt;li&gt;Who is working on what (standups, kick-offs, etc)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Gaming it&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I feel very strongly about working this way over a pull request approach when you are working on a team you trust.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most of my team until recently were very unfamiliar with this way of working so I made a silly dashboard on one of the TVs which showed who committed to the main branch most over a given week. It penalises you if you push a change which breaks the build.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/5gG7OMf.png&#34; alt=&#34;ci-league dashboard&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;After just a few weeks this slight nudging has improved the team&#39;s approach to CI, we&#39;ve had significantly less merge conflicts, people are refactoring more often and the number of failed builds has also dropped.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/ci-league&#34;&gt;The code for it is on github&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And if you have docker, you can run it with&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;$ docker run -p 8000:8000 quii/ci-league&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want it to look at a private repo you&#39;ll need to supply a &lt;a href=&#34;https://github.com/settings/tokens&#34;&gt;github personal access token&lt;/a&gt; as an environment variable&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;$ docker run -p 8000:8000 -e GITHUB_TOKEN=supersecret quii/ci-league&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It doesn&#39;t do any fancy auto-refreshing but most browsers have extensions to auto refresh a tab, we set it to update every 10 minutes here.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As usual in software, we seem to suffer as an industry of remembering the &lt;em&gt;why&lt;/em&gt; of all of these fancy terms.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you appreciate the why of CI you may not fall in to the trap of blindly applying best practices that work in a different context to the one you are working in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pull-requests in an open source project make total sense and work great. In a different context it can add overhead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should instead focus on what your environment your team is working in, the constraints you have and use principles like CI to guide what process best fits.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 28 Nov 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The carbon footprint of your website</title>
      <link>https://quii.dev/The_carbon_footprint_of_your_website</link>
      <description>&lt;p&gt;Stumbled across &lt;a href=&#34;https://www.websitecarbon.com&#34;&gt;https://www.websitecarbon.com&lt;/a&gt; which measures the carbon footprint of your website.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve always believed in lightweight, efficient websites to deliver content. I firmly believe in not using client-side JS unless absolutely necessary because not everyone has an Internet Telephone Professional Maximum on a 4g connection.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://dev.to/quii/the-web-i-want-43o&#34;&gt;I ranted about this and riled up the community about this subject here&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.websitecarbon.com/website/www-quii-dev/&#34;&gt;My website is 94% cleaner than other websites tested&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&#39;s your score?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Given the huge amount of evidence pointing to how website performance effects users &lt;em&gt;and&lt;/em&gt; the environment, what are you going to do about it?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For more on this check out the slides of this excellent talk &lt;a href=&#34;https://twitter.com/hanopcan/status/1187675166236643329&#34;&gt;https://twitter.com/hanopcan/status/1187675166236643329&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Wed, 13 Nov 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The ghost of Henry Ford is ruining your development team</title>
      <link>https://quii.dev/The_ghost_of_Henry_Ford_is_ruining_your_development_team</link>
      <description>&lt;p&gt;People talk a lot about &amp;quot;lean&amp;quot;. Maybe they&#39;ve read &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Machine_That_Changed_the_World_(book)&#34;&gt;The Machine That Changed The World&lt;/a&gt; and were inspired by how lean manufacturing transformed the motor industry. They read how Japanese companies became incredibly efficient and blew the competition out of the water, and then they took that to their software development team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgflip.com/3evf0h.jpg&#34; alt=&#34;You keep saying lean, i do not think it means what you think it means&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This sounds good, but too often, I feel like people miss the real genius of lean manufacturing and continue to run their organisation with a top-heavy command and control structure; the only difference is a constant message of&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Be more efficient! Stop being wasteful! LEEEEEAN&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Agile, DevOps and other buzzwords get a lot of their inspiration from lean manufacturing, and these ways of working gain their efficiencies (and other, more significant benefits) broadly by &lt;strong&gt;empowering development teams and giving them responsibility&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;A primer on mass production&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Before Henry Ford’s assembly line, cars were made to order by craftsmen. It took a long time to make them, and they were reserved for the wealthy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The assembly line made it possible to make cars cheaply, which made them accessible to a far broader market.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;How?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It’s a big subject, but here are some pithy bullet points:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To reduce costs, he needed to produce cars at high volume with low-skilled workers, not craftsmen.&lt;/li&gt;&#xA;&lt;li&gt;The assembly line was a collection of expensive, inflexible machinery that scaled to volume and could be operated by cheap labour doing very simple tasks.&lt;/li&gt;&#xA;&lt;li&gt;Emphasis on standardisation, being able to replace one worker with another cheaply and easily.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Problems&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The assembly line was very intolerant to disruption, small problems could cause big problems and stop the line. To mitigate this, they:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Had to add lots of buffers, such as storing supplies, space and additional workers to smooth production&lt;/li&gt;&#xA;&lt;li&gt;preferred to accept defects and fix them after the car was made, rather than to stop the line&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The work was very dispiriting. Ford even passed on some of the savings and profits to his workers by heavily increasing their salaries, but people just didn’t want to do the same tedious task 100s of times a day.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The assembly line is heavily optimised for volume with expensive, specific machines meant it was very inflexible, so creating different cars was a very difficult and costly endeavour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When designing new cars, it took what we would recognise as a very waterfall approach, of a project being passed around many departments and problems being unsurfaced way too late due to poor feedback loops, and not a good structure of ownership.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Lean manufacturing&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Japanese carmakers studied the production line and tried a different way. When you hear about Kanban and Kaizen in agile circles, it all came from here.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From &lt;a href=&#34;https://en.wikipedia.org/wiki/Lean_manufacturing&#34;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For many, lean is the set of &amp;quot;tools&amp;quot; that assist in the identification and steady elimination of waste. &lt;strong&gt;As waste is eliminated, quality improves while production time and cost are reduced&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;There isn&#39;t a canonical &amp;quot;lean&amp;quot; way of working, but the one that resonates strongest with me is &amp;quot;The Toyota Way.&amp;quot;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The Toyota Way, in which the focus is upon improving the &amp;quot;flow&amp;quot; or smoothness of work, thereby steadily eliminating mura (&amp;quot;unevenness&amp;quot;) through the system and not upon &#39;waste reduction&#39; per se... The implementation of smooth flow exposes quality problems that already existed, and thus waste reduction naturally happens as a consequence. The advantage claimed for this approach is that it naturally takes a system-wide perspective, whereas a waste focus sometimes wrongly assumes this perspective&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3&gt;How does Lean try to reduce waste?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Another big subject and there are good resources on it with a Google search. The main drive of it from my perspective, is actively trying to identify waste and then fix it. Lean describes 3 types&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Mura&lt;/strong&gt;: Waste due to changes in demand. Lean advocates a &amp;quot;pull&amp;quot; system rather than &amp;quot;push&amp;quot;. So you only make a car if there is demand for it rather than trying to forecast demand which is often difficult and makes supply inconsistent. In software, this would be akin to perhaps making a cheap prototype to prove an idea before committing to a bigger endeavour.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Muri&lt;/strong&gt;: Waste by trying to do too much stuff at once. This is why if you&#39;re doing Kanban and not observing work-in-progress limits, you&#39;re not doing Kanban. It can sometimes feel counter-intuitive that you can go faster by doing less work, but you&#39;ve probably worked in a situation where a team is working really hard, and everything feels chaotic and unreliable. This is also why smaller teams are generally preferable.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Muda&lt;/strong&gt;: Non-value-adding work. A classic example in software would be developers constantly struggling with flaky builds and not addressing the underlying causes.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Lean emphasises the idea of &amp;quot;flow&amp;quot;, optimising the processes for delivery and reducing interruptions in the production process. (think about trunk-based development vs pull requests here)&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Quality&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;For quality, you adopt &lt;a href=&#34;https://en.wikipedia.org/wiki/Kaizen&#34;&gt;Kaizen&lt;/a&gt;, striving for perfection and hunting down the root causes of issues and fixing them. You embrace a culture of quality across the value stream, not after the product is &amp;quot;finished&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Command and control vs autonomy and empowerment&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What I mainly took from the book &amp;quot;The Machine That Changed The World&amp;quot; was how it contrasted mass manufacturing and lean manufacturing with respect to management.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lean manufacturing acknowledges that it&#39;s impossible to heavily micro-manage the production of a complicated product like a car with thousands of people working on it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The best way for Kaizen to work is to coach and empower the do-ers to find the best ways to deliver.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Signs you&#39;re not in a lean company&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;People with job titles of &amp;quot;manager&amp;quot; or &amp;quot;leader&amp;quot; but are nothing more than coordinators&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When designing new cars, there is the idea of the Shusa (not sushi!), who in short, was &lt;em&gt;actually&lt;/em&gt; in charge of things. They could bring people to help and make decisions and were not worried about being overruled by the whims of upper management; they were empowered to make the project work. People would say that these people actually made their mark on a project &amp;quot;Oh, you can tell that&#39;s a Dan car because of X, Y and Z&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Contrast that to places I&#39;ve worked where people have had very lofty job titles but no actual empowerment and were nothing more than a communication funnel between the people who actually make things and the people who could actually make decisions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How common is it in our industry for tech leads to be miserable simply because they&#39;re promoted into what they&#39;ll actually call a &amp;quot;shit shield&amp;quot;. Seriously, can we stop saying that as if it&#39;s a good thing? It&#39;s a problem.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;A leader should be able to lead&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The development team has no say in priorities&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Lean famously relies on Kaizen, the concept of continually striving for perfection. In lean plants, workers can stop the plant if they find a problem, and they work hard to make sure it doesn&#39;t happen again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you see something technically wrong and slowing your team down, how empowered are you to fix it? Do you work with a scrum master who will humour you but probably thinks &amp;quot;technical stories&amp;quot; are a &amp;quot;waste&amp;quot;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Being lean and efficient is not simply done by only working on the most important feature at a given time. It&#39;s about the builders working hard to create a &lt;em&gt;system and environment&lt;/em&gt; that can be worked on efficiently. That takes the form of the usual best practices; tightening and improving feedback loops, continuous delivery, easy to set up, simple delivery pipeline, excellent code, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The lean plants worked hard to reduce problems and defects and to give themselves flexibility. This only happened because the workers were given the autonomy to make it happen, not micromanagement from above.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How does your team compare? Can you fix problems when you see them (which is the best time), or do you have to wait for the &amp;quot;technical debt sprint&amp;quot;?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;All teams have a standard, immutable way of working&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Toyota didn&#39;t just make up lean and be successful; they had to practice and iterate at it to figure out how to be good. Your IT teams need to practice and work at being lean.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You also have to understand that we don&#39;t have teams of resources; they are individuals working on different problems. If you want to get the most out of people, you need to give them autonomy to figure out how they can work together most effectively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How does a team get better at working together if they can&#39;t gather feedback by retrospecting and improving how they work?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Larger organisations often talk about standardisation to allow developers to move between teams. That in itself isn&#39;t a bad thing, but it&#39;s not essential as autonomy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;If you want teams to be empowered enough to practice Kaizen and let them find how to work efficiently, you have to accept that teams will work differently.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is fine, and in my experience, moving between teams is always a challenge, even if everyone works the same way because teams are more complicated than a set of tools and processes.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The people who write the software are not responsible for QA or running it in production&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In mass manufacturing, the assembly line optimised itself for volume and would defer any quality problems to the end of the line, where another team would pick things up and fix them. The issue is that the feedback loop didn&#39;t exist, and systemic problems would never get addressed, which brings waste.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I consider a QA column in a Kanban wall as a smell. QA in lean worlds is a part of the entire development process, not something tacked on at the end. QA is a responsibility and an inherent quality of a good team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://continuousdelivery.com/principles/&#34;&gt;From the continuous delivery website&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;It’s much cheaper to fix problems and defects if we find them immediately—ideally before they are ever checked into version control, by running automated tests locally. Finding defects downstream through inspection (such as manual testing) is time-consuming, requiring significant triage. Then we must fix the defect, trying to recall what we were thinking when we introduced the problem days or perhaps even weeks ago.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;If you&#39;re throwing your software over a wall to an ops team, how do you expect to write a sound system?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Boredom&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you&#39;re trying to turn your development team into a homogeneous assembly line pumping out JIRA tickets at volume you might start to bore some people (and probably build some crappy products).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You probably pay your engineers a lot of money because they&#39;re presumably quite clever, so why are you denying them the space to &lt;em&gt;think and take responsibility&lt;/em&gt;?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve worked on projects which should be, to be honest, quite boring but turned out to be great fun because I worked in an engaged, empowered and fun team who took pride in doing things the &amp;quot;right&amp;quot; way and practised Kaizen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It was excellent for the team, and we delivered the project, which was initially seen as very risky and tricky, with very little stress. Not only that but what we learned with respect to shipping software was adopted by other teams in the organisation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Kaizen is fun, rewarding and will improve your outcomes.&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Too scared to release and get feedback&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In the book &lt;em&gt;Lean Thinking: Banish Waste and Create Wealth in Your Corporation,&lt;/em&gt; it says&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Identify value from the customer&#39;s perspective&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Doing this with software products is notoriously difficult, but it&#39;s made even more difficult if you don&#39;t have the courage to release your software to the world and gather feedback.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Too often, the software is managed as a project which &amp;quot;ends&amp;quot; (this is nonsense, obviously), and no one takes any lessons from the customers. &lt;strong&gt;This is the ultimate form of waste&lt;/strong&gt; that Lean strives to fight against.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The transformational lean technologies and methodologies&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I think it’s interesting to think about the transformative technologies over the past few years and how they relate to lean. I think a lot of things appear big and transformative but are they solving real problems? Are they helping you be lean?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Docker&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Docker is an empowering technology allowing developers to use technology far more freely. Rather than asking for permission to use technology and have it installed in production etc., we can use whatever we like because we just ship containers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The main benefit for me, though, is it has made the difference between a local computer and production much smaller, which allows developers to take more responsibility for the quality of their software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Synonymous with moving away from highly specialised, inflexible tooling in the mass manufacturing world&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;DevOps&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;DevOps is lean. It is about tightening feedback loops, improving the quality of our tooling and processes and taking responsibility for our software. Read The Phoenix Project. Just do it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Cloud computing (e.g. AWS)&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Again this is another empowering development which lets the shop floor workers quickly adapt their technology landscape to solve problems. Synonymous with having more flexible machinery in the lean car factories as opposed to highly specialised ones from mass manufacturing.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up - we&#39;re not building cars.&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Agile and DevOps have taken a lot of lessons from the lean manufacturing of cars. All of them are about building complicated things with lots of people, which requires a different way of thinking vs mass manufacturing if you wish to do it efficiently with a happy workforce.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But when you&#39;re reading about lean, it&#39;s important to remember that we software developers have different goals.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We&#39;re not trying to build software at volume.&lt;/li&gt;&#xA;&lt;li&gt;We&#39;re trying to deliver the promise of software, products that are malleable and can change to users&#39; needs quickly and cheaply.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;A big thing about lean is identifying value from a customer&#39;s perspective and eliminating anything that doesn&#39;t contribute to it. People take this lesson in software too aggressively to deprioritise anything that isn&#39;t a feature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The thing is, this is just a very immature way of looking at what you&#39;re building. Not only are you making a product, but you&#39;re building a &lt;em&gt;system&lt;/em&gt; that your developers work on. It&#39;s akin to not allowing your factory workers to improve the assembly line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The factory is as important as the cars, and the system is as important as the software product.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &amp;quot;real&amp;quot; customer &lt;em&gt;does&lt;/em&gt; benefit from the following:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Making it more operable so it has less downtime.&lt;/li&gt;&#xA;&lt;li&gt;Improving the test suite so the software can be changed easily to meet customer needs quickly&lt;/li&gt;&#xA;&lt;li&gt;etc. etc&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Examining the &amp;quot;value stream&amp;quot; for waste is excellent; nothing more dispiriting than working on something for months with no objective evidence it&#39;ll benefit anyone.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Too often, though, this is led by &amp;quot;product&amp;quot; people with little collaboration from the technical side. The team cannot practice Kaizen and wastes its time working around technical debt, slow builds, poor feedback loops, manual testing etc. This results in a product becoming too hard to change and can&#39;t react to what the user wants in the long run. A far cry from the flexible, malleable and efficient development system we&#39;re all supposedly striving for.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This comes back to what I wrote earlier, is your tech lead empowered to lead? Or is she just making sure you put estimates on JIRA tickets? Is she treated as an equal when deciding priorities for work? Does she have to argue constantly for scraps of time for the team to practice Kaizen whilst passive-aggressively being accused of being wasteful for even suggesting non-feature work?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Final final thought&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;From Wikipedia again&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The cultural and managerial aspects of lean are arguably more important than the actual tools or methodologies of production itself. There are many examples of lean tool implementation without sustained benefit, and these are often blamed on weak understanding of lean throughout the whole organization.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Replace the word lean with &amp;quot;agile&amp;quot;, and I think you&#39;ll have a lot of software developers nodding with knowing looks on their faces.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 31 Oct 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Go back to basics with MVC</title>
      <link>https://quii.dev/Go_back_to_basics_with_MVC</link>
      <description>&lt;p&gt;This is another follow up post to an episode of &lt;a href=&#34;https://changelog.com/gotime/92&#34;&gt;Go time&lt;/a&gt; I listened to the other day which seems to get my creative juices flowing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It talked about web development in Go and a few things stuck out to me&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;A cautionary tale of generating HTML&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Early on in the episode it was described how the built-in template library wasn&#39;t very expressive and described that the Go Buffalo framework uses &lt;a href=&#34;https://github.com/gobuffalo/plush&#34;&gt;Plush&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Powerful, flexible, and extendable, Plush is there to make writing your templates that much easier.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3&gt;Enter Jade&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;8ish years ago I worked on a pretty major project which was written in Scala. We decided to use the Jade template engine to generate our HTML which, like Plush allows you to do a lot of clever coding inside your templates.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This felt amazing at first but &lt;strong&gt;quickly became a nightmare&lt;/strong&gt;. With the flexibility Jade gave us we made a bit of a mess. Our templates became ugly, hard to understand and difficult to test as more and more business logic leaked into our templates&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In software I often see &lt;em&gt;flexibility&lt;/em&gt; as rope that a team can hang itself with and I tend to prefer very opinionated and constrained things (like Go!).&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What did we learn?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Software engineers are doomed to relearn things. We had forgotten about separation of concerns, in particular the guidance the Model-View-Controller design pattern prescribes.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;MVC&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&#39;s quite surprising how badly people misunderstand MVC. If you go on Reddit or Twitter you will hear people telling other developers that &amp;quot;MVC isn&#39;t suited to Go&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Often people seem to think MVC is about folder structures, class names, or other fairly superficial concerns. So when developers from say a Rails background show their Go code with an array of folders they get derided and thrown to the lions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;MVC does not prescribe folder structure and I worry a lot of people seem to miss the point of the principle.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&#34;&gt;Model–View–Controller (usually known as MVC) is an architectural pattern commonly used for developing user interfaces that divides an application into three interconnected parts.&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h3&gt;Controller&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Intercepts &amp;quot;requests&amp;quot; (such as HTTP), parses them and then calls the appropriate &amp;quot;Model&amp;quot;, getting some kind of data as a result and then sends it to a &amp;quot;View&amp;quot;. In the Go world, that&#39;s usually a &lt;code&gt;http.Handler&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Model&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Loosely, it&#39;s where your domain logic lives. I personally think it&#39;s quite poorly named but the important thing is the separation of concern. It must be decoupled from the Controller and View, so if you see anything HTTP related passed through from the controller it&#39;s likely you&#39;re violating that decoupling. They should also know nothing about views.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;View&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It doesn&#39;t know anything about controllers or models. It should probably get passed to it some kind of &lt;code&gt;ViewModel&lt;/code&gt; which is just a collection of data it needs to render a view. A well designed view is simple and doesnt have domain logic; because templates are very hard to test cheaply.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What do these principles buy you?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Your domain code is cleanly separated from the rest of the system so it is easy to test and can be &amp;quot;plugged in&amp;quot; to different uses beyond your web server; for example a CLI tool, or just as a package for others to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is trivial to create and edit views as they are merely mappings from a bundle of generic data into HTML (or whatever). It also makes them more accessible for frontend developers et al.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Your controller has clear concerns and are also easy to test.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Circling back to the start, I would be very cautious about something that allows me to write very expressive code for my view. These kind of tools trick developers with promises of convenience and power but often lead to leaky abstractions unless you are very disciplined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now have a think about all the tutorials you may have read around HTTP servers and Go. The good ones will recommended all of these principles without perhaps just calling them out. Rather than the community dancing around the idea of MVC, just embrace it. It&#39;s a tried and tested pattern and most people advocate it anyway, just not explicitly. If we were explicit then maybe there wouldn&#39;t be a new post every week about how to structure a HTTP server!&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How to structure your web app&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Understand &lt;em&gt;the idea&lt;/em&gt; of MVC.&lt;/li&gt;&#xA;&lt;li&gt;Your &lt;code&gt;http.Handler&lt;/code&gt;s are your controllers, make sure they only do things controllers do according to above.&lt;/li&gt;&#xA;&lt;li&gt;All your other business logic (Model) lives elsewhere, in packages centered around real things. If it&#39;s a bank i&#39;d maybe have packages for &lt;code&gt;Account&lt;/code&gt;, &lt;code&gt;Currency&lt;/code&gt;, &lt;code&gt;Customer&lt;/code&gt; e.t.c. Your controller will call things in your packages to do useful stuff.&lt;/li&gt;&#xA;&lt;li&gt;Depending on what you&#39;re building you can just use the encoding packages to spit out XML or JSON, or if it&#39;s HTML just use &lt;code&gt;template/html&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 25 Jul 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Functional programming and Go</title>
      <link>https://quii.dev/Functional_programming_and_Go</link>
      <description>&lt;p&gt;The &lt;a href=&#34;https://changelog.com/gotime/87&#34;&gt;Go Time podcast on functional programming (fp)&lt;/a&gt; was an interesting listen and as someone who has done many years of both Scala and Go it&#39;s a topic I&#39;m interested in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The show talked about the stuff you&#39;d expect, pure functions, immutability, higher-order functions etc. Here&#39;s some thoughts I&#39;d like to add on top.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Errors&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s have a look at a function written in a few programming languages&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Divide(x, y int) (int, error)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Scala&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def Divide(x: Int, y: Int): Either[Exception, Int]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Java&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;public Int Divide(int x, int y)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;What does the Go and Scala one have in common that Java does not?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;You can trust the function from the signature&lt;/em&gt;. You do not need to read the function body to understand that it can fail.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Java it would not be surprising for the function to throw an exception. Unless the author decided to use checked exceptions it means the user has to inspect the function body to see if anything potentially bad can happen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At first throwing exceptions can seem convenient but in the long run become a pain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;FP values explicitness and and so does Go&lt;/strong&gt;. It is recommended that you do not write packages that &lt;code&gt;panic&lt;/code&gt; because that makes your code more difficult to work with and trust.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Errors as values&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Go (and Scala) treat errors as &lt;em&gt;values&lt;/em&gt; just like any other data in our system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Crucially there is &lt;strong&gt;no special special syntax to work with errors&lt;/strong&gt;. &lt;code&gt;Error&lt;/code&gt; is just an interface that everyone happens to use as it&#39;s built-in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md&#34;&gt;Go 2 has proposals to make working with errors more convenient&lt;/a&gt; because error handling in Go right now can be fairly verbose.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;a, err := Divide(2, 0)&#xA;&#xA;if err != nil {&#xA;    return 0, fmt.Errorf(&amp;quot;oh no %v&amp;quot;, err)&#xA;}&#xA;&#xA;b, err := Divide(2, 2)&#xA;&#xA;if err != nil {&#xA;    return 0, fmt.Errorf(&amp;quot;oh no %v&amp;quot;, err)&#xA;}&#xA;&#xA;return a + b, nil&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For Go 2, we would like to make error checks more lightweight, reducing the amount of Go program text dedicated to error checking. We also want to make it more convenient to write error handling, raising the likelihood that programmers will take the time to do it.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;The main problem with errors in Go is they do not safely compose and this is an important property (and advantage) of FP&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s see how Scala let&#39;s us safely compose functions that can sometimes fail&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;val result: Either[Exception, Int] = for {&#xA;  a &amp;lt;- Divide(2, 0)&#xA;  b &amp;lt;- Divide(2, 2)&#xA;} yield(a + b)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3&gt;Explanation&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In this case, the 2nd &lt;code&gt;Divide&lt;/code&gt; would not run and &lt;code&gt;result&lt;/code&gt; would equal &lt;code&gt;Left[ArithmeticException(&amp;quot;Cannot divide by 0&amp;quot;)]&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;If we changed the first divide so it would work it would run the 2nd &lt;code&gt;Divide&lt;/code&gt; and then in the yield it is able to used the &amp;quot;unwrapped&amp;quot; &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; to simply add them as if they are two normal &lt;code&gt;Int&lt;/code&gt;s&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I need to stress this &lt;em&gt;isn&#39;t special syntax&lt;/em&gt;, the &lt;code&gt;for&lt;/code&gt; syntax works with &lt;em&gt;any&lt;/em&gt; type that has &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;flatMap&lt;/code&gt;. (&lt;em&gt;cough&lt;/em&gt; monads &lt;em&gt;cough&lt;/em&gt;)&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Go 2, errors and generics&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I worry about the proposals around errors in Go 2 because they are making errors &amp;quot;special&amp;quot;. &lt;a href=&#34;https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md#draft-design&#34;&gt;It is adding ad-hoc syntax&lt;/a&gt; and that doesn&#39;t feel very &amp;quot;Go like&amp;quot; to me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go 2 also has generics under consideration but the two topics seem to be discussed in separation a lot of the time. FP has identified patterns and datatypes for &lt;em&gt;safely&lt;/em&gt; and easily working with errors; and they almost all rely on generics.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead of&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type Reader interface {&#xA;        Read(p []byte) (n int, err error)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Maybe we could have&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type Reader interface {&#xA;        Read(p []byte) Either&amp;lt;Int, error&amp;gt;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;With a good generics solution we wouldn&#39;t have to have special syntax that &lt;em&gt;only work with errors&lt;/em&gt; and errors can retain their non-special status they have right now.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We&#39;d still need &lt;em&gt;some&lt;/em&gt; kind of new syntax to help with composition (like the Scala one earlier) but it wouldn&#39;t be tied down to a specific datatype; and could be based on proven and existing patterns from other FP languages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;(Incidentally, I find Kotlin suffers from trying too hard to not be like Scala and instead invents syntax and idioms which are not as portable as learning about say.... monads.)&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Go already values a lot of principles from FP. Rather than creating new syntax that makes errors somehow different and special, wouldn&#39;t it be better if Go continued to lean on FP principles to help Go programmers work with errors a little more elegantly?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I could be totally off the mark (this is very likely, I am not a language designer). It can definitely be argued that bringing in more elements from FP is also not &amp;quot;Go like&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Generics are simple but not always easy. Adding ad-hoc syntax to work with errors is probably easy but not simple.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go errors right now are &lt;em&gt;simple and easy&lt;/em&gt;. If we dont want to tack on more complexity just for the sake of making code less verbose... maybe dont bother and leave errors as they are?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What&#39;s the difference between simple and easy?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.infoq.com/presentations/Simple-Made-Easy/&#34;&gt;Simple made easy&lt;/a&gt; is one of my most favourite tech talks.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Rich Hickey emphasizes simplicity’s virtues over easiness’, showing that while many choose easiness they may end up with complexity, and the better way is to choose easiness along the simplicity path.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 10 Jun 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>How to go fast</title>
      <link>https://quii.dev/How_to_go_fast</link>
      <description>&lt;p&gt;This article is for anyone who works in software and wants to keep life simple, less stressful but still keep their employer happy. You&#39;ll see how by making simple choices and sticking to well-understood, proven principles you can ship software and not burn everyone out along the way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The business have arbitrarily given your team a year to make &lt;em&gt;a website thing&lt;/em&gt; and they&#39;ve got many grandiose ideas. Don&#39;t be tempted to spend lots of time planning up front imagining big architectures and backlogs around all this ambition. This is the path to failure, premature optimisation and broken promises.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only promise you&#39;ll make is you will showcase what you&#39;ve done every 2 weeks and accept steering from the business on &lt;em&gt;actual problems&lt;/em&gt; and not feature decisions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We know going fast is important but so is the quality of the system we&#39;re making and the mental health of our team. &lt;strong&gt;We will go really fast but we will always be doing it in a sustainable way.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We don&#39;t want to be stressed out about big-bang releases, having to do big scary refactors or obsessing over irrelevant estimates for work that we may not ever actually do.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Get things clear&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Often things fall apart quickly when there isn&#39;t good alignment as to what the point of the work is. It&#39;s essential that &lt;em&gt;everyone&lt;/em&gt; on the team (not just the blessed leaders) understand:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Who the user is&lt;/li&gt;&#xA;&lt;li&gt;What problem they have that we&#39;re solving&lt;/li&gt;&#xA;&lt;li&gt;What are the &lt;em&gt;non-goals&lt;/em&gt; (to increase transparency, manage expectations, e.t.c.)&lt;/li&gt;&#xA;&lt;li&gt;How do we know this is worthwhile and how do we validate our efforts?&lt;/li&gt;&#xA;&lt;li&gt;How do we avoid the sunk-cost fallacy? What would make us radically change approach or cancel the project?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;At all points everyone should &lt;strong&gt;understand the why of what they are doing&lt;/strong&gt;. You&#39;re paying developers megabucks to think and if they don&#39;t understand the goal they won&#39;t be thinking about it. Instead, they&#39;ll either not think at all or focus on the wrong things.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Start writing software and iterate quickly&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Start with hello world, fully deployed with continuous delivery.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means if a commit goes to the main branch and passes the tests it should be deployed to production, ideally on a public URL that you can share with your users and stakeholders to get feedback quickly on your product.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;We always want a small and focused vision for the team to be working on.&lt;/strong&gt; Developing small things is easy and likely to succeed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thinking about delivering tons of features causes teams to over-complicate and makes decision-making difficult.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With lots of features up in the air there&#39;s the temptation to expand the team and this also slows things down. &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Mythical_Man-Month&#34;&gt;See: The Mythical Man-Month&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead, we work on the next most important thing, based on business expertise, research, developer know-how and feedback from our users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/G3uQ9Jc.png&#34; alt=&#34;Agile skateboard&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We will carry on continuously delivering small features iteratively indefinitely.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Rules and principles&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;1 Small co-located team&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Small teams deliver quicker than big teams because the lines of communication are small and the amount of work being done at once has to be small. Large teams working on lots of things breeds confusion and complexity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Having multiple small teams working on clearly separated things &lt;em&gt;can&lt;/em&gt; work but requires good coordination. It&#39;s a lot easier to define those teams on architectural lines once you have a mature product. I think it&#39;s a mistake to take a &lt;em&gt;new&lt;/em&gt; project with lots of unknowns and try and divide it amongst many teams because the architecture needs to be very flexible at this point and therefore the teams &lt;em&gt;wont be able to work independently, they will be coupled&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In my experience being able to very easily talk to someone is important. The informal chats you have by just turning to your colleague is invaluable in breaking down the barriers of sharing ideas and building relationships. To me this is why I prefer to work in a co-located team because it minimises friction in communication.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If it is possible make sure the decision makers, such as the product owner be sitting with the team too. I wrote how work would be showcased every 2 weeks as a ritual but what&#39;s even better is quickly trying out an idea and getting immediate feedback from the stakeholders. This levels up the teams collective knowledge of the domain and massively reduces waste.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Pair programming most of the time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Pairing helps you to write better software and helps cross-pollinate skills, ideas and domain knowledge. It will help grow your team and will improve relationships which will in general make everyone happier!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Don&#39;t mandate it from 9-5 though as it becomes very tiring very quickly. People need time and space to think.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;No branches and no pull requests&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;You have a small team that are pairing. You &lt;em&gt;should&lt;/em&gt; be talking to each other all the time so you don&#39;t need pull requests to check code is OK. You&#39;re better off shipping it and getting feedback. You should be able to trust two people to get things right most of the time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pull requests are great for open source projects where you don&#39;t have implicit trust in every contributor. In a small team you don&#39;t need it and you need to take advantage of very tight feedback loops by reducing ceremony in writing software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A big theme of these rules is removing barriers to feedback loops and this means we can change software easily. Someone shipping code that isn&#39;t ideal &lt;strong&gt;is not the end of the world, just fix it and move on - don&#39;t introduce complicated processes that slows everything down&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Have a minimal deployment pipeline&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Maintaining pipelines and various non-live environments can become burdensome. At least at the start of the project all you really need is:&lt;/p&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Run tests&lt;/li&gt;&#xA;&lt;li&gt;Deploy to live&lt;/li&gt;&#xA;&lt;li&gt;Run smoke tests&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;p&gt;If you find yourself trying to justify a non-live environment ask yourself&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What is it that I cant test locally or in production? Why?&lt;/li&gt;&#xA;&lt;li&gt;What are the costs and ramifications of being only able to test a thing in a particular environment?&lt;/li&gt;&#xA;&lt;li&gt;What delays does this cause to shipping to production?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Most of the time you probably wont have good answer to these questions.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Continuously deliver to live on green builds.&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This gives you:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fast feedback&lt;/li&gt;&#xA;&lt;li&gt;Force you to automate tests&lt;/li&gt;&#xA;&lt;li&gt;Force you to write actually shippable code&lt;/li&gt;&#xA;&lt;li&gt;Forces you to have good monitoring&lt;/li&gt;&#xA;&lt;li&gt;Makes releases a stress-free, non-event&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;/Why_you_should_deploy_on_Friday_afternoon&#34;&gt;This has been written about a lot&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://images-na.ssl-images-amazon.com/images/I/41TLwbsl8eL._SX329_BO1,204,203,200_.jpg&#34; alt=&#34;Accelerate book cover&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.amazon.co.uk/Accelerate-Software-Performing-Technology-Organizations/dp/1942788339&#34;&gt;And is proven to be how high-performing teams work&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Manually shipping a week or two weeks worth of work takes time and is risky; releasing small things constantly is easy and less risky.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Write tests&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;They enable you to iterate quickly with confidence. Cant do continuous delivery without them and you cant go fast if you have to manually check things all the time.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Monolith, not microservices&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Writing distributed systems is a pain in the arse and I&#39;d rather avoid that pain until I actually need to distribute my system. &lt;a href=&#34;https://martinfowler.com/bliki/Yagni.html&#34;&gt;YAGNI&lt;/a&gt; in other words.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Refactoring in-process method calls is far easier than changing API calls. Deploying one application is much easier to deploy than orchestrating many system deployments etc etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve worked on microservice projects in the past but my last project was a monolith and we moved so much faster because we cut out a huge number of issues to contend with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In order to do microservices you have to think &lt;em&gt;how&lt;/em&gt; you will break your system up into small components which leads nicely to...&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Don&#39;t design up front&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Just ship some code, if you make something useful and keep refactoring and iterating a design will emerge from &lt;em&gt;reality&lt;/em&gt; rather than developers arguing over a whiteboard.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Refactor continuously&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Bad code makes you go slow. Bad code tends to get worse. So refactor continuously, don&#39;t have a refactor sprint and don&#39;t put it off. Don&#39;t ask for permission, if it&#39;s bad just fix it. You want the pay-off from refactoring &lt;em&gt;now&lt;/em&gt;, not 3 months later.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Half the perceived problems of monoliths come from people writing bad code. If you maintain the quality of the code &lt;em&gt;real&lt;/em&gt; abstractions based on &lt;em&gt;real usage&lt;/em&gt; will emerge and then if you need to break up your monolith there will be obvious ways to do.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Avoid writing an SPA, embrace progressive enhancement&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;SPAs bring a mountain of complexity that most projects don&#39;t need. You&#39;re probably not building Gmail so stop pretending you &lt;em&gt;need&lt;/em&gt; to write an SPA. You can get React on your CV at 10% time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Instead prefer to use progressive enhancement techniques by writing semantic HTML, decorated with CSS and a sprinkle of JavaScript to enhance the experience a little when necessary. Even better, don&#39;t write &lt;em&gt;any&lt;/em&gt; client-side JavaScript if you can.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Don&#39;t obsess over pixel-perfect design&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Writing HTML and CSS can be challenging and very time-consuming if you have a designer being overly precious about their design looking pixel perfect in every browser.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We are writing code for &lt;em&gt;users&lt;/em&gt; not designers and most of the time they wont care if it looks a bit different in Firefox compared to Chrome.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Save time, effort and stress by challenging what is good enough for your users.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Simple designs are simple to implement, elaborate designs are complicated to implement&lt;/strong&gt;. If your designer is giving you difficult to implement web pages, remind them we&#39;re trying to go fast.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Ship the first 80%, polish it later&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Related to the above it is a total waste of time to really perfect a certain feature in respect to design and UX if it turns out that it is a feature that isn&#39;t needed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have seen a team spend weeks polishing a search feature on a website in respect to its design and its JavaScript only for it to be thrown away a few months later because the fundamental idea was wrong in the first place.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Ship enough to get feedback and prove the idea&lt;/em&gt;, once you&#39;ve done that you can then spend time polishing it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The people who write the software are the ones that are on support for it&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This responsibility must be coupled with the empowerment to make the system maintainable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the people creating the system are the ones who have the threat of getting called at 3am because it is down they are more likely to ship more robust code.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Use mature, proven tools&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It doesn&#39;t matter if you go fast with &lt;em&gt;shiny thing&lt;/em&gt; if you then leave and no one can build or understand your code anymore.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Get a consensus in your team of what you&#39;d all enjoy writing with that is appropriate for the task at hand. Don&#39;t pick up a new programming language that is unfamiliar to everyone - remember we&#39;re trying to go fast.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It must be simple to build the software&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;There should be a minimal amount of setup required to run and test the project. It is totally unacceptable to be unable to build a project just because it hasn&#39;t been touched for a few months or a key person has left. If it takes an individual more than an hour to setup the project you have failed hard.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With technologies like Docker it is trivial to configure a project so it has all it&#39;s 3rd party dependencies such as databases available locally.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It should not be reliant on a particular setup of a computer (beyond installing a few key things such as the JVM, Go or whatever). It must not be reliant on a 3rd party system for it to run &amp;amp; test locally.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To help enforce this, configure whatever CI tool you are using to automatically build the software every morning; even if no one has committed to it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;If the build is red, stop&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The tests must always be passing. If you have unreliable tests, stop and fix them. Flaky tests have cost me many hours of my time in the past.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Actually sit with users and watch them work&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;What &lt;em&gt;the business&lt;/em&gt; thinks the users needs vs what the user &lt;em&gt;actually&lt;/em&gt; needs is often very different. I have been lucky enough to witness this first hand where we saved ourselves a ton of work by actually watching a user at work and we were able to identify a very cheap and simple solution that they actually want vs the extremely costly solution the business proposed.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;User stories are a conversation starter&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If a user story prescribes exactly what software to write, who made that decision? Why? How did they know they were correct?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This kind of approach of a &amp;quot;tech lead&amp;quot; or whatever deciding how to write the software creates disillusioned developer robots who have no sense of ownership and stories that are &amp;quot;blocked&amp;quot; because they have not been blessed by some over-controlling leader.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;User stories should describe a user problem and when it is picked up the team figures out a way to do it and then they execute that plan, simple as that. This has a higher chance of success because more people are thinking about the problem and makes people feel involved.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Each ticket have some kind of measure of success that should be validated when enough data/research is gathered.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Understand that &lt;em&gt;we are all software developers&lt;/em&gt;&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In my imaginary company if you consider yourself a &amp;quot;backend&amp;quot; developer and consequently get blocked because the &amp;quot;frontend&amp;quot; developer is sick consider yourself fired. Same if the UX designer is away and you don&#39;t want to take a punt at how a particular interaction should pan out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should have an appreciation of all aspects of software development. That&#39;s not to say you have to be an expert in everything but being blocked because a particular person is away is unacceptable.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should feel empowered enough to give whatever task a try. It doesn&#39;t matter if it&#39;s not perfect because it&#39;s better to ship something that is 70% good and then when the expert returns you can then &lt;strong&gt;iterate&lt;/strong&gt; on the software to make it better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I said pairing earlier I didn&#39;t just mean &amp;quot;backend developers&amp;quot; or whatever. Everyone should be involved. If a UX designer is interviewing users it is their responsibility to bring along someone else to get experience of this skill and learn about the users. This kind of knowledge sharing is &lt;em&gt;vital&lt;/em&gt; to make individuals that feel invested in the project and the team.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Have 10/20% time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Allocate time for everyone to work on whatever they want and be strict about it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We work in a creative profession and we need some space to breathe, learn things and try out different ideas.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a great perk for the team, can help avoid burnout and can help bring new ideas that can bring great improvements to your systems down the line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s also important because it allows &lt;em&gt;everyone&lt;/em&gt; to spend time developing their skills, not just people who happen to have a lot of free time and little responsibility. 10% time is important for diversity.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Don&#39;t plan extensively beyond 6 weeks&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Having a vision of the future is fun, but keep it vague and aspirational. Remember a team focused on one or two features is far more productive than one which is worrying about 10 imaginary requirements.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;No Jira worship, no estimates, no timekeeping, no burn-up charts&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;All a massive waste of time, causes friction and I haven&#39;t seen a single burn-up chart in my career deliver any kind of &lt;em&gt;actual useful information&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember we have committed to showing  &lt;em&gt;&lt;strong&gt;real working software&lt;/strong&gt;&lt;/em&gt; frequently, &lt;strong&gt;not imaginary charts&lt;/strong&gt; which are at best educated guesses. Finger in the air guesses are fine, adding up story points for tickets that have no hope of being actually looked at in the next 3 months is worthless.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://agilemanifesto.org/&#34;&gt;Individuals and interactions over processes and tools&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;By all means have a simple, physical wall with the columns of ready for dev, in dev &amp;amp; done but much more than that it just becomes silly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;JIRA, or any other tool should be used to help your process; not define it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Keep work-in-progress (WIP) low&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;It&#39;s important to understand what WIP really means. I&#39;ve worked in teams where a story is &amp;quot;done&amp;quot; but not actually in the hands of users. If you&#39;ve written code that&#39;s not being used by your customer, that code is work in progress.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ever worked in a team with many stories in progress, and the team seems to be in a perpetual state of chaos with no clear value being actually delivered?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This usually stems from:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Stories being parked due to being &amp;quot;blocked&amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;Not &amp;quot;real&amp;quot; stories, but technical tasks that may have some hypothetical value someday&lt;/li&gt;&#xA;&lt;li&gt;Stories with unclear problems to solve&lt;/li&gt;&#xA;&lt;li&gt;Developers not empowered to solve problems, but are rather seen as JIRA ticket robots&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Over time high WIP causes tons of work to not being finished properly which will add a ton of friction to your team and reduce productivity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://sourcelevel.io/blog/stop-measuring-your-team-measure-the-flow&#34;&gt;Optimise for flow, not resource allocation&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When you start work have a clear understanding of how it will get into the hands of users and if it&#39;s unclear, don&#39;t even start it.&lt;/li&gt;&#xA;&lt;li&gt;Be wary of depending on other &amp;quot;silos&amp;quot; and if you can find ways to remove them.&lt;/li&gt;&#xA;&lt;li&gt;Teams can also form inner silos which you need to avoid, don&#39;t be in scenarios where only certain developers can do certain tasks.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If you empower developers and make them responsible for delivering value they will find ways to unblock themselves and improve flow.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The way to move fast is not imagine the perfect product, architecture, design a backlog and then execute it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The way you move fast is by iterating quickly with low-effort, proven methodologies and communicating with each other as you learn through your iterations.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Optimise your processes so that your team can fearlessly and quickly change software. This way you will be able to build a good product guided by constant feedback loops.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is no one true way to create great teams who can ship great products but in my experience so far these principles seem to stand up well. Your way might be different and that&#39;s fine but ask yourself if your team is as good as it could be. Retrospection is always important to help your team adapt to new conditions.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Footnotes&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This article has been &lt;a href=&#34;https://muchtrans.com/translations/how-to-go-fast.ko.html&#34;&gt;translated into Korean&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 02 Mar 2019 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Work 2018</title>
      <link>https://quii.dev/Work_2018</link>
      <description>&lt;p&gt;This post is a summary of work stuff over the past year which covers&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The ways of working, agile and innovation&lt;/li&gt;&#xA;&lt;li&gt;Microservices vs monoliths&lt;/li&gt;&#xA;&lt;li&gt;Kotlin&lt;/li&gt;&#xA;&lt;li&gt;Writing a book (kinda)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;The team and the way we work&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I rejoined Springer Nature (SN) August 2017 on the exciting premise of being in&#xA;an &amp;quot;innovations team&amp;quot; where we would attempt to maybe make scientific&#xA;publishing a bit better using technology.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was a little sad to be moving from a role mainly writing Go to Kotlin but programming languages aren&#39;t everything.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What mainly drew me to the role was the understanding that we would be&#xA;empowered to work in the way we felt was best.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am a big believer in &amp;quot;agile&amp;quot;; &lt;a href=&#34;https://agilemanifesto.org/&#34;&gt;the &lt;em&gt;actual&lt;/em&gt; agile&lt;/a&gt;, not the project management nightmare. Stuff like&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Individuals and interactions over processes and tools&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;and&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Responding to change over following a plan&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;We are a small team of 3 developers, UX and a BA. We work very collaboratively&#xA;with little ceremony. To give an idea our &amp;quot;stand up&amp;quot; is having a chat about what were working on and our general thoughts on the work. By that definition we have at least 3 standups a day.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The responsibilities within the team are more or less shared and we rely on&#xA;each other&#39;s relevant expertise to fill in the blanks when needed. I wont be&#xA;blocked if our UX is away at a meeting, I&#39;ll just take a punt knowing it&#xA;probably wont be &lt;em&gt;that bad&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We talk a lot and we iterate quickly and actually talk to real users, rather&#xA;than fighting through many layers of hierarchy.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With all of us feeling empowered and involved it means ideas come to us quickly&#xA;and if we think we have a good idea we&#39;ll discuss it and try it out. We dont&#xA;worry about 2 week long inceptions and prioritising backlogs; if we think its&#xA;the best thing for us to try now, we&#39;ll do it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we get things wrong, we dont sweat it; we can change software. Someone very&#xA;clever said&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A prototype is worth a thousand meetings&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;The other key to us moving quickly is really acknowledging the rule that the&#xA;last 10% of work takes 90% of the time and just avoid doing it (at least in the short term).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We often say&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Perfect is the enemy of good&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;We would rather ship something that we hope is good, get feedback and iterate on it rather than tying ourselves in knots over perfection.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In terms of the way we work, I couldn&#39;t be happier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what are we working on?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The work&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We were connected with a journal who had some exciting ideas around data and community building. We thought we could create a minimal viable product (MVP) peer-review system (PRS) to experiment around these topics to hopefully learn how SN can help in these areas.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We thought Trello was cool and we had actually interviewed someone who managed&#xA;a journal entirely in Trello so it seemed like a nice way to bootstrap&#xA;a &amp;quot;system&amp;quot; quickly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Our first iteration was a simple HTML form for an author to submit a manuscript&#xA;which would create a card in Trello. An editor could then inspect the details&#xA;and then manage the whole process of peer review manually themselves (for now);&#xA;when they were happy with the manuscript if they dragged it into the column&#xA;&amp;quot;Ready for publication&amp;quot; our web hook would listen to that event and then create&#xA;an XML payload for publishing. We turned this around in about a week and felt&#xA;&lt;em&gt;really rad&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there we kept iterating, adding a simple peer reviewer search and inviting&#xA;mechanism (still in Trello).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Eventually though Trello&#39;s limitations in terms of UI were becoming burdensome.&#xA;It was great to prototype and we learned some interesting things from the users&#xA;about their processes but ultimately we needed to control the UI. We didnt&#xA;throw it all out and start again though; we just kept iterating, creating new&#xA;web pages to address our new needs until eventually we didnt need Trello at&#xA;all.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We &amp;quot;launched&amp;quot; with our MVP submission system for the journal in September.&#xA;Since then we have carried on iterating based on user feedback and have been&#xA;working to try and make the arduous quality assurance process for&#xA;a manuscript a more pleasant experience.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Innovation vs invention and politics&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What exactly &lt;em&gt;is&lt;/em&gt; an innovations team? Some would think that we should be using&#xA;blockchain terraform kubernetes machine-learning wizzpops to change the world.&#xA;&lt;em&gt;I&lt;/em&gt; have often wondered why what we build isn&#39;t massively transformative.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The talk &lt;a href=&#34;https://vimeo.com/140302789&#34;&gt;Building a winning product and UX strategy from the Kano Model by Jared Spool&lt;/a&gt; gives a lot of clarity for me.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The real tension is between invention and innovation. Innovation is where we improve a customer&#39;s experience so that they are &amp;quot;delighted&amp;quot;. It&#39;s moving the needle from basic&#xA;expectation to something that&#39;s awesome.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Invention&lt;/em&gt; is when you are launching moonshots at ideas that are wild and&#xA;likely to fail but if they work, could radically change the business.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I think about how software teams &lt;em&gt;should&lt;/em&gt; be working, they should all be&#xA;empowered to be innovating. This to me is what agile is all about. You should&#xA;be shipping a product, collecting feedback and as a team understanding it as&#xA;best you can and then trying out new ideas to move the needle.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is exactly how we work and I feel this is how every team should work. You&#xA;dont work on a project (because there&#39;s no such thing as projects in software), you work on a product. You start small and keep iterating for as long as the product lives.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As your product grows so does your team, in terms of improving the way it&#xA;works, how it collects information and ideas around a domain so that it can&#xA;deliver better ideas quicker.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe software wouldn&#39;t be so expensive if we treated it properly rather than shipping on a particular date and then letting it rot; then re-writing it all over again forever and ever.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My conclusion for all of this, is the &lt;strong&gt;whole concept of an innovations team is an anti-pattern&lt;/strong&gt;. Which is a bit weird to say given that was what was sold to me when I rejoined SN.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The joy of monolith&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Until this year I have mainly worked on microservices systems for a good 4-5&#xA;years. I really like the approach of microservices in terms of creating small&#xA;systems within bounded contexts and then gluing them together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve always understood that the cost of this is in terms of increased&#xA;complexity in terms of continuous integration (CI), deployments and making sure your system actually works with unreliable network calls and evolving APIs so they dont break each other (e.g. consumer driven contracts)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This year we monolith&#39;d our system and it has been incredibly liberating.&#xA;I sometimes sit in meetings with other teams as they discuss their technical&#xA;stuff and I had forgotten how much of a pain building distributed systems is.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This has really cemented the idea that you should &lt;em&gt;always&lt;/em&gt; start monolith when&#xA;building a system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;YAGNI is getting ignored too much these days, every recruitment email tells me&#xA;how its a &amp;quot;greenfield microservices project&amp;quot; - sounds awful!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s &lt;em&gt;far&lt;/em&gt; easier and quicker to build your monolith and &lt;em&gt;then&lt;/em&gt; you get to see&#xA;the actual areas in your system that could be separate services when the API is&#xA;a bit more mature.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A lot of the perceived downsides of monoliths are often fixed with just good&#xA;programming practices.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At some point a system does get too big and you&#39;ll need to break it up, but&#xA;maybe we should worry about building a successful system before breaking it up?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Kotlin&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;After writing Kotlin for about 18 months I conclude it&#39;s alright.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It feels like a nice happy medium between Scala and Java, but I do miss a number of Scala features such as for comprehensions and pattern matching.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These features being missing often makes Kotlin code &lt;em&gt;more&lt;/em&gt; complicated than the Scala equivalents which flies in the face of the opinion of Kotlin being simpler than Scala. Abstractions &lt;em&gt;can and should&lt;/em&gt; bring simplicity when used correctly.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Scala for better or worse gives you a lot of abstraction power which most developers will make a mess with if I&#39;m being honest; often myself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The Kotlin compiler is still &lt;em&gt;quite&lt;/em&gt; slow; especially compared to Go but its much faster than Scala.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Ad-hoc Kotlin-isms&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I&#39;m personally not a fan of the ad-hoc syntax it has added for commonly known problems. It feels like to me they have really tried to avoid acknowledging monads and the like but have invented different things to learn instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve run into occasions where I&#39;ve wanted to refactor code from a &lt;code&gt;T?&lt;/code&gt; (nullable &lt;code&gt;T&lt;/code&gt;) to a &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; which is harder than it should be.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Scala the abstraction is clearly modeled so you can call &lt;code&gt;map&lt;/code&gt; on them in a consistent way. So if you change the type there&#39;s very few code changes to make.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Kotlin if it is nillable you do things like &lt;code&gt;myThing?.let{it + 1}&lt;/code&gt;. But with lists its &lt;code&gt;myList.map{it + 1}&lt;/code&gt;. To me it&#39;s annoying that they&#39;re different. A nullable thing &lt;em&gt;should&lt;/em&gt; be seen as a collection of one or zero items in it.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Ecosystem&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;From what I read a lot of people writing Kotlin still want to feel the comfort of Java land in respect to relying heavily on frameworks like Spring. I &lt;em&gt;really&lt;/em&gt; dont want to use a massive framework and neither does anyone in our team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thankfully SN has invested a lot of time and effort in allowing some developers to create a lovely library called &lt;a href=&#34;https://github.com/http4k/http4k&#34;&gt;http4k&lt;/a&gt; which offers a simple API to create web servers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I still feel Go is probably my weapon of choice for a general purpose language but it&#39;s certainly not a deal-breaker for me to write Kotlin.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Writing Learn Go with tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;SN is nice enough to have 10% time. In March I thought it would be fun to do a TDD guide of a &amp;quot;Hello, world&amp;quot; function in Go.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I stumbled on a nice approach of starting with a simple function and iterating on it, adding new features of Go as the software grows and gets refactored which results in quite a nice flow of learning.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It got a lot of attention on the social media thing, getting top of hacker news and lots of internet points in Github stars.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This led to me feeling &lt;em&gt;very&lt;/em&gt; motivated and since then I&#39;ve written &lt;strong&gt;a lot of content&lt;/strong&gt; covering most of the Go programming language syntax by TDD-ing useful functionality.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/learn-go-with-tests&#34;&gt;You can find it all on Github&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For me the most amazing thing is some members of Chinese Go community have &lt;a href=&#34;https://studygolang.gitbook.io/learn-go-with-tests&#34;&gt;translated it into Chinese!&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A few chapters have been contributed by other members from the community and a lot of my terrible grammar has been fixed. Overall there are 39 different contributors to the project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Using &lt;a href=&#34;https://quii.gitbook.io/learn-go-with-tests/&#34;&gt;gitbook it has a website&lt;/a&gt; and I used &lt;a href=&#34;https://pandoc.org/&#34;&gt;Pandoc&lt;/a&gt; to generate an &lt;a href=&#34;https://github.com/quii/learn-go-with-tests/releases&#34;&gt;epub file&lt;/a&gt; from the markdown that the content is written in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The feedback from the community has been invaluable and very rewarding. Committing knowledge to paper is challenging and trying to explain what you know helps solidify your ideas and I am sure the whole experience has improved me as a developer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am immensely proud of this work and intend to press on with it to add more content in 2019.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Small empowered teams can deliver useful software quickly&lt;/li&gt;&#xA;&lt;li&gt;Innovations team is an organisational smell&lt;/li&gt;&#xA;&lt;li&gt;Build a useful, well-engineered monolith first. Then you&#39;ll see how you can break it up into smaller pieces as you feel the pain of a big codebase. Taking on the challenges of microservices will just slow your project down at first.&lt;/li&gt;&#xA;&lt;li&gt;Kotlin is pretty good, but like all programming languages has its annoyances&lt;/li&gt;&#xA;&lt;li&gt;Writing down stuff you&#39;re interested in is challenging and rewarding. When people say nice things about your work its very nice, so if &lt;em&gt;you&lt;/em&gt; like someone&#39;s work do tell them as it&#39;ll make their day.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sun, 30 Dec 2018 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Tests Talk</title>
      <link>https://quii.dev/The_Tests_Talk</link>
      <description>&lt;p&gt;This month I had the opportunity to present some ideas floating around in my head around tests, refactoring and design at the &lt;a href=&#34;https://www.meetup.com/Go-London-User-Group/&#34;&gt;Go London User Group&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=Kwtit8ZEK7U&#34;&gt;Here&#39;s a link to the video&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://docs.google.com/presentation/d/1wTV0Y5XYA-bo7gzj7x0541qJJ4eSbVa0jvq-DCJVttA/edit?usp=sharing&#34;&gt;Here are the slides&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you&#39;re not into videos, here&#39;s wordy version of it.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Software&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The promise of software is that it can change. This is why it is called &lt;em&gt;soft&lt;/em&gt; ware, it is malleable compared to hardware. A great engineering team should be an amazing asset to a company, writing systems that can evolve with a business to keep delivering value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So why are we so bad at it? How many projects do you hear about that outright fail? Or become &amp;quot;legacy&amp;quot; and have to be entirely re-written (and the re-writes often fail too!)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How does a software system &amp;quot;fail&amp;quot; anyway? Can&#39;t it just be changed until it&#39;s correct? That&#39;s what we&#39;re promised!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A lot of people are choosing Go to build systems because it has made a number of choices which one hopes will make it more legacy-proof.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compared to my previous life of Scala where &lt;a href=&#34;/Scala_-_Just_enough_rope_to_hang_yourself&#34;&gt;I described how it has enough rope to hang yourself&lt;/a&gt;, Go has only 25 keywords and &lt;em&gt;a lot&lt;/em&gt; of systems can be built from the standard library and a few other small libraries. The hope is that with Go you can write code and come back to it in 6 months time and it&#39;ll still make sense.&lt;/li&gt;&#xA;&lt;li&gt;The tooling in respect to testing, benchmarking, linting &amp;amp; shipping is first class compared to most alternatives.&lt;/li&gt;&#xA;&lt;li&gt;The standard library is brilliant.&lt;/li&gt;&#xA;&lt;li&gt;Very fast compilation speed for tight feedback loops&lt;/li&gt;&#xA;&lt;li&gt;The Go backward compatibility promise. It looks like Go will get generics and other features in the future but the designers have promised that even Go code you wrote 5 years ago will still build. I literally spent weeks upgrading a project from Scala 2.8 to 2.10.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Even with all these great properties we can still make terrible systems, so we should look to the past and understand lessons in software engineering that apply no matter how shiny (or not) your language is.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In 1974 a clever software engineer called Manny Lehman wrote &lt;a href=&#34;https://en.wikipedia.org/wiki/Lehman%27s_laws_of_software_evolution&#34;&gt;Lehman&#39;s laws of software evolution&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The laws describe a balance between forces driving new developments on one hand, and forces that slow down progress on the other hand.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;These forces seem like important things to understand if we have any hope of not being in an endless cycle of shipping systems that turn into legacy and then get re-written over and over again.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Law of Continuous Change&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Any software system used in the real-world must change or become less and less useful in the environment&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;It feels obvious that a system &lt;em&gt;has&lt;/em&gt; to change or it becomes less useful but how often is this ignored?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Many teams are incentivised to deliver a project on a particular date and then moved on to the next project. If the software is &amp;quot;lucky&amp;quot; there is at least some kind of hand-off to another set of individuals to maintain it, but they didn&#39;t write it of course.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People often concern themselves with trying to pick a framework which will help them &amp;quot;deliver quickly&amp;quot; but not focusing on the longevity of the system in terms of how it needs to evolve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even if you&#39;re an incredible software engineer, you will still fall victim to not knowing the future needs of your system. As the business changes some of the brilliant code you wrote is now no longer relevant.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lehman was on a roll in the 70s because he gave us another law to chew on.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Law of Increasing Complexity&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;As a system evolves, its complexity increases unless work is done to reduce it&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;What he&#39;s saying here is we can&#39;t have software teams as blind feature factories, piling more and more features on to software in the hope it will survive in the long run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We &lt;strong&gt;have&lt;/strong&gt; to keep managing the complexity of the system as the knowledge of our domain changes.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Refactoring&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are &lt;em&gt;many&lt;/em&gt; facets of software engineering that keeps software malleable, such as:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Developer empowerment&lt;/li&gt;&#xA;&lt;li&gt;Generally &amp;quot;good&amp;quot; code. Sensible separation of concerns, etc etc&lt;/li&gt;&#xA;&lt;li&gt;Communication skills&lt;/li&gt;&#xA;&lt;li&gt;Architecture&lt;/li&gt;&#xA;&lt;li&gt;Observability&lt;/li&gt;&#xA;&lt;li&gt;Deployability&lt;/li&gt;&#xA;&lt;li&gt;Automated tests&lt;/li&gt;&#xA;&lt;li&gt;Feedback loops&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;I am going to focus on refactoring. It&#39;s a phrase that gets thrown around a lot &amp;quot;we need to refactor this&amp;quot; - said to a developer on their first day of programming without a second thought.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Where does the phrase come from? How is refactoring just different from writing code?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I know that I and many others have &lt;em&gt;thought&lt;/em&gt; we were doing refactoring but we were mistaken&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://martinfowler.com/bliki/RefactoringMalapropism.html&#34;&gt;Martin Fowler describes how people are getting it wrong&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;However the term &amp;quot;refactoring&amp;quot; is often used when it&#39;s not appropriate. If somebody talks about a system being broken for a couple of days while they are refactoring, you can be pretty sure they are not refactoring.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;So what is it?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Factorisation&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When learning maths at school you probably learned about factorisation. Here&#39;s a very simple example&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Calculate &lt;code&gt;1/2 + 1/4&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To do this you &lt;em&gt;factorise&lt;/em&gt; the denominators, turning the expression into&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;2/4 + 1/4&lt;/code&gt; which you can then turn into &lt;code&gt;3/4&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can take some important lessons from this. When we &lt;em&gt;factorise the expression&lt;/em&gt; we have &lt;strong&gt;not changed the meaning of the expression&lt;/strong&gt;. Both of them equal &lt;code&gt;3/4&lt;/code&gt; but we have made it easier for us to work with; by changing &lt;code&gt;1/2&lt;/code&gt; to &lt;code&gt;2/4&lt;/code&gt; it fits into our &amp;quot;domain&amp;quot; easier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you refactor your code, you are trying to find ways of making your code easier to understand and &amp;quot;fit&amp;quot; into your current understanding of what the system needs to do. Crucially &lt;strong&gt;you should not be changing behaviour&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;An example in Go&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Here is a function which greets &lt;code&gt;name&lt;/code&gt; in a particular &lt;code&gt;language&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Hello(name, language string) string {&#xA;&#xA;  if language == &amp;quot;es&amp;quot; {&#xA;     return &amp;quot;Hola, &amp;quot; + name&#xA;  }&#xA;&#xA;  if language == &amp;quot;fr&amp;quot; {&#xA;     return &amp;quot;Bonjour, &amp;quot; + name&#xA;  }&#xA;&#xA;  // imagine dozens more languages&#xA;&#xA;  return &amp;quot;Hello, &amp;quot; + name&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Having dozens of &lt;code&gt;if&lt;/code&gt; statements doesn&#39;t feel good and we have a duplication of concatenating a language specific greeting with &lt;code&gt;,&lt;/code&gt; and the &lt;code&gt;name.&lt;/code&gt; So I&#39;ll refactor the code.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Hello(name, language string) string {&#xA;    return fmt.Sprintf(&#xA;        &amp;quot;%s, %s&amp;quot;,&#xA;        greeting(language),&#xA;        name,&#xA;    )&#xA;}&#xA;&#xA;var greetings = map[string]string {&#xA;  es: &amp;quot;Hola&amp;quot;,&#xA;  fr: &amp;quot;Bonjour&amp;quot;,&#xA;  //etc..&#xA;}&#xA;&#xA;func greeting(language string) string {&#xA;  greeting, exists := greetings[language]&#xA;&#xA;  if exists {&#xA;     return greeting&#xA;  }&#xA;&#xA;  return &amp;quot;Hello&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The nature of this refactor isn&#39;t actually important, what&#39;s important is I haven&#39;t changed behaviour.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When refactoring you can do whatever you like, add interfaces, new types, functions, methods etc. The only rule is you don&#39;t change behaviour&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;When refactoring code you must not be changing behaviour&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;This is very important. If you are changing behaviour at the same time you are doing &lt;em&gt;two&lt;/em&gt; things at once. As software engineers we learn to break systems up into different files/packages/functions/etc because we know trying to understand a big blob of stuff is hard.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We don&#39;t want to have to be thinking about lots of things at once because that&#39;s when we make mistakes. I&#39;ve witnessed so many refactoring endeavours fail because the developers are biting off more than they can chew.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When I was doing factorisations in maths classes with pen and paper I would have to manually check that I hadn&#39;t changed the meaning of the expressions in my head. How do we know we aren&#39;t changing behaviour when refactoring when working with code, especially on a system that is non-trivial?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Those who choose not to write tests will typically be reliant on manual testing. For anything other than a small project this will be a tremendous time-sink and does not scale in the long run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;In order to safely refactor you need unit tests&lt;/strong&gt; because they provide&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Confidence you can reshape code without worrying about changing behaviour&lt;/li&gt;&#xA;&lt;li&gt;Documentation for humans as to how the system should behave&lt;/li&gt;&#xA;&lt;li&gt;Much faster and more reliable feedback than manual testing&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;An example in Go&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;A unit test for our &lt;code&gt;Hello&lt;/code&gt; function could look like this&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestHello(t *testing.T) {&#xA;  got := Hello(“Chris”, es)&#xA;  want := &amp;quot;Hola, Chris&amp;quot;&#xA;&#xA;  if got != want {&#xA;     t.Errorf(&amp;quot;got &#39;%s&#39; want &#39;%s&#39;&amp;quot;, got, want)&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;At the command line I can run &lt;code&gt;go test&lt;/code&gt; and get immediate feedback as to whether my refactoring efforts have altered behaviour. In practice it&#39;s best to learn the magic button to run your tests within your editor/IDE.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You want to get in to a state where you are doing&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Small refactor&lt;/li&gt;&#xA;&lt;li&gt;Run tests&lt;/li&gt;&#xA;&lt;li&gt;Repeat&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;All within a very tight feedback loop so you don&#39;t go down rabbit holes and make mistakes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Having a project where all your key behaviours are unit tested and give you feedback well under a second is a very empowering safety net to do bold refactoring when you need to. This helps us manage the incoming force of complexity that Lehman describes.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;If unit tests are so great, why is there sometimes resistance to writing them?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;On the one hand you have people (like me) saying that unit tests are important for the long term health of your system because they ensure you can keep refactoring with confidence.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On the other you have people describing experiences of unit tests actually &lt;em&gt;hindering&lt;/em&gt; refactoring.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Ask yourself, how often do you have to change your tests when refactoring? Over the years I have been on many projects with very good test coverage and yet the engineers are reluctant to refactor because of the perceived effort of changing tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the opposite of what we are promised!&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Why is this happening?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Imagine you were asked to develop a square and we thought the best way to accomplish that would be stick two triangles together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/ela7SVf.jpg&#34; alt=&#34;Two right-angled triangles to form a square&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We write our unit tests around our square to make sure the sides are equal and then we write some tests around our triangles. We want to make sure our triangles render correctly so we assert that the angles sum up to 180 degrees, perhaps check we make 2 of them, etc etc. Test coverage is really important and writing these tests is pretty easy so why not?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A few weeks later The Law of Continuous Change strikes our system and a new developer makes some changes. She now believes it would be better if squares were formed with 2 rectangles instead of 2 triangles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/1G6rYqD.jpg&#34; alt=&#34;Two rectangles to form a square&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;She tries to do this refactor and gets mixed signals from a number of failing tests. Has she actually broken important behaviours here? She now has to dig through these triangle tests and try and understand what&#39;s going on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;It&#39;s not actually important that the square was formed out of triangles&lt;/em&gt; but &lt;strong&gt;our tests have falsely elevated the importance of our implementation details&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Favour testing behaviour rather than implementation detail&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When I hear people complaining about unit tests it is often because the tests are at the wrong abstraction level. They&#39;re testing implementation details, overly spying on collaborators and mocking too much.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I believe it stems from a misunderstanding of what unit tests are and chasing vanity metrics (test coverage).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If I am saying just test behaviour, should we not just only write system/black-box tests? These kind of tests do have lots of value in terms of verifying key user journeys but they are typically expensive to write and slow to run. For that reason they&#39;re not too helpful for &lt;em&gt;refactoring&lt;/em&gt; because the feedback loop is slow. In addition black box tests don&#39;t tend to help you very much with root causes compared to unit tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So what &lt;em&gt;is&lt;/em&gt; the right abstraction level?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Writing effective unit tests is a design problem&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Forgetting about tests for a moment, it is desirable to have within your system self-contained, decoupled &amp;quot;units&amp;quot; centered around key concepts in your domain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I like to imagine these units as simple Lego bricks which have coherent APIs that I can combine with other bricks to make bigger systems. Underneath these APIs there could be dozens of things (types, functions et al) collaborating to make them work how they need to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For instance if you were writing a bank in Go, you might have an &amp;quot;account&amp;quot; package. It will present an API that does not leak implementation detail and is easy to integrate with.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have these units that follow these properties you can write unit tests against their public APIs. &lt;em&gt;By definition&lt;/em&gt; these tests can only be testing useful behaviour. Underneath these units I am free to refactor the implementation as much as I need to and the tests for the most part should not get in the way.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Are these unit tests?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;YES&lt;/strong&gt;. Unit tests are against &amp;quot;units&amp;quot; like I described. They were &lt;em&gt;never&lt;/em&gt; about only being against a single class/function/whatever.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Bringing these concepts together&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We&#39;ve covered&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Refactoring&lt;/li&gt;&#xA;&lt;li&gt;Unit tests&lt;/li&gt;&#xA;&lt;li&gt;Unit design&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;What we can start to see is that these facets of software design reinforce each other.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Refactoring&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Gives us signals about our unit tests. If we have to do manual checks, we need more tests. If tests are wrongly failing then our tests are at the wrong abstraction level (or have no value and should be deleted).&lt;/li&gt;&#xA;&lt;li&gt;Helps us handle the complexities within and between our units.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Unit tests&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Give a safety net to refactor.&lt;/li&gt;&#xA;&lt;li&gt;Verify and document the behaviour of our units.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;(Well designed) units&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Easy to write &lt;em&gt;meaningful&lt;/em&gt; unit tests.&lt;/li&gt;&#xA;&lt;li&gt;Easy to refactor.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Is there a process to help us arrive at a point where we can constantly refactor our code to manage complexity and keep our systems malleable?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Why Test Driven Development (TDD)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Some people might take Lehman&#39;s quotes about how software has to change and overthink elaborate designs, wasting lots of time upfront trying to create the &amp;quot;perfect&amp;quot; extensible system and end up getting it wrong and going nowhere.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is the bad old days of software where an analyst team would spend 6 months writing a requirements document and an architect team would spend another 6 months coming up with a design and a few years later the whole project fails.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I say bad old days but this still happens!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Agile teaches us that we need to work iteratively, starting small and evolving the software so that we get fast feedback on the design of our software and how it works with real users;  TDD enforces this approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;TDD addresses the laws that Lehman talks about and other lessons hard learned through history by encouraging a methodology of constantly refactoring and delivering iteratively.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Small steps&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write a small test for a small amount of desired behaviour&lt;/li&gt;&#xA;&lt;li&gt;Check the test fails with a clear error (red)&lt;/li&gt;&#xA;&lt;li&gt;Write the minimal amount of code to make the test pass (green)&lt;/li&gt;&#xA;&lt;li&gt;Refactor&lt;/li&gt;&#xA;&lt;li&gt;Repeat&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;As you become proficient, this way of working will become natural and fast.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&#39;ll come to expect this feedback loop to not take very long and feel uneasy if you&#39;re in a state where the system isn&#39;t &amp;quot;green&amp;quot; because it indicates you may be down a rabbit hole.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&#39;ll always be driving small &amp;amp; useful functionality comfortably backed by the feedback from your tests.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The strength of software is that we can change it. &lt;em&gt;Most&lt;/em&gt; software will require change over time in unpredictable ways; but dont try and over-engineer because it&#39;s too hard to predict the future.&lt;/li&gt;&#xA;&lt;li&gt;Instead we need to make it so we can keep our software malleable. In order to change software we have to refactor it as it evolves or it will turn into a mess&lt;/li&gt;&#xA;&lt;li&gt;A good test suite can help you refactor quicker and in a less stressful manner&lt;/li&gt;&#xA;&lt;li&gt;Writing good unit tests is a design problem so think about structuring your code so you have meaningful units that you can integrate together like Lego bricks.&lt;/li&gt;&#xA;&lt;li&gt;TDD can help and force you to design well factored software iteratively, backed by tests to help future work as it arrives.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Tue, 18 Dec 2018 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Web I Want</title>
      <link>https://quii.dev/The_Web_I_Want</link>
      <description>&lt;p&gt;&lt;a href=&#34;https://dev.to/quii/the-web-i-want-43o&#34;&gt;I originally posted this at Dev.to, where you can see some comments&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post will very much sound like I want you all to get off my lawn - because I do.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How has the web become like this?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;img src=&#34;https://i.imgur.com/en9Fc0c.png&#34; alt=&#34;From this very website&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The other day my partner was browsing the web on her two-year-old Chromebook, it struggled to run a number of sites as they loaded ads, gifs, videos and tons of JavaScript to do absolutely nothing of value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Every day I am frustrated at my phone as it chugs along trying to display a blog post. The post is there behind a sea of JavaScript and autoplaying videos.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This all sounds a bit first world problems, but it&#39;s far, far worse for those in developing nations. Do you know how bad satellite Internet is compared to what most of us have here in the west? It is awful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://wearesocial-net.s3.amazonaws.com/uk/wp-content/uploads/sites/2/2017/01/Slide091.png&#34;&gt;Graph of mobile connection speeds&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The World Wide Web is supposed to be a leveler, something that brings knowledge everywhere and yet developers every day are making it harder for those who need the Internet to work well the most.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s take a look at how things have &amp;quot;progressed&amp;quot; with the Internet.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;20ish years ago&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;I knew nothing about programming or the web&lt;/em&gt;, but using HTML that was returned in response to HTTP requests, I managed to build a website.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It delivered as much content as most websites today. It was more accessible, ran faster and easier to develop then 90% of the stuff you&#39;ll read on websites teaching about web development. It did not need a build tool, transpilation, a framework or any of the other nonsense that is now required to build a website.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;10-15 years ago&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;People were fed up with nested tables and spacer images. The web was losing its roots of being a content delivery platform.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I was working on websites like the above in my placement year on my degree. I started reading articles on &lt;a href=&#34;https://alistapart.com&#34;&gt;A list Apart&lt;/a&gt; about how we should be pushing for &lt;em&gt;semantic markup&lt;/em&gt;, where HTML simply describes a document of content, and then it is styled using this thing called CSS.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Eventually I ran into &lt;a href=&#34;http://www.csszengarden.com/&#34;&gt;CSS Zen Garden&lt;/a&gt; which is a website that showcases what you could do with CSS.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The idea is the markup is the same and the website has submissions from developers showing different designs purely using CSS.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The HTML remains the same, the only thing that has changed is the external CSS file. Yes, really.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This website had a profound impact on my attitude to web development. &lt;em&gt;It clicked&lt;/em&gt;. HTML for content, CSS for style. No JavaScript required, no tables needed for layout, no spacer images.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;Just pure HTML decorated with CSS.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It felt exciting to be part of a community that took real pride in delivering beautiful looking content in the leanest, simplest and most accessible way possible.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Not only did this make websites more &lt;em&gt;accessible&lt;/em&gt; and fast to run but in some ways made them easier to develop. Suddenly generating the markup from the server wasn&#39;t horrible, because you didn&#39;t worry about style, just the content and the hypermedia controls.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Still things were quite difficult. CSS support wasn&#39;t amazing, and we still didn&#39;t have a lot of semantic elements with HTML4 so there were &lt;em&gt;a lot of &lt;code&gt;div&lt;/code&gt;s&lt;/em&gt;. Firebug had just come out which was a huge boost, but it was still hard to make a consistent experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I seem to recall Gmail coming out around this time, and it was amazing. Suddenly the web could be actual &lt;em&gt;applications&lt;/em&gt;. This was interesting and groundbreaking, but had a real negative impact too. Soon enough people thought that the promotional website for their local pub had to have as much JavaScript as Gmail.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;5 years-ish till present&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I now browse the Internet with a few tabs open and I have somehow downloaded many megabytes of data, my laptop is on fire and yet in terms of &lt;em&gt;actual content delivery&lt;/em&gt; nothing has really changed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is a not exaggerated summary of today&#39;s attitudes&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Scores of people who just want to deliver their content and have it look somewhat nice are convinced you need every web technology under the sun to deliver text and some pictures.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You&#39;re not a frontend developer unless you know Vue/React/whatever. &lt;a href=&#34;https://twitter.com/iamdevloper/status/704970333300740096&#34;&gt;&lt;em&gt;You&#39;re mocked&lt;/em&gt; if you dare to just write the bare minimum JavaScript you need for your website&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The page refreshing is seen as a massive problem for users, and it must be avoided at all costs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For some reason people are building tons of SPAs (single page web apps). The reasons stated are for speed and ease of developer use. (&lt;em&gt;I don&#39;t buy sending tons of JavaScript to a browser will ever be as fast as just some damn HTML. Also, it&#39;s not as easy as putting some HTML files on the Internets&lt;/em&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You see these &lt;em&gt;laughable&lt;/em&gt; posts where developers jump through dozens of hoops to make their website &amp;quot;fast and performant&amp;quot;. They struggle because of the underlying technical choices, and then I&#39;m still downloading half a megabyte of data to read 500 words. It&#39;s embarrassing.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;There are a few things I want you to take away from this post&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Most websites are about delivering and exploring content. HTML is &lt;em&gt;amazing&lt;/em&gt; for this, and &lt;strong&gt;you don&#39;t need JavaScript&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;In fact JavaScript is actively harmful. It is poison for low power devices, horrible for people on low bandwidth and requires extra effort to keep it accessible and fast.&lt;/li&gt;&#xA;&lt;li&gt;So much effort poured into all this JavaScript. You seem to have to learn &lt;em&gt;so much&lt;/em&gt;, new frameworks, new build tools, new ways of testing; &lt;strong&gt;and most of the time it is making the experience worse for your users&lt;/strong&gt;. The churn is unreal too, every year it feels like there is a new framework or tool that is going to change everything.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;In practice your website would do everything it needed to with some HTML files linking to some CSS&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;So what is The Web I want?&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Semantic, accessible, HTML. This means it works for everyone, is fast to download and is less effort than writing React components.&lt;/li&gt;&#xA;&lt;li&gt;CSS to make it look pretty. Don&#39;t use JavaScript for visual effects.&lt;/li&gt;&#xA;&lt;li&gt;Small images, when needed. Enough of these &lt;em&gt;hilarious&lt;/em&gt; 4mb GIFs.&lt;/li&gt;&#xA;&lt;li&gt;Most websites should be ready to read after a 10kb download.&lt;/li&gt;&#xA;&lt;li&gt;If I cant use your website without JavaScript being turned on then you don&#39;t know what you&#39;re doing.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h4&gt;So no JavaScript, really?&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;JavaScript of course still has its place and when used tastefully can improve the usability of a website. However, think carefully about the libraries and frameworks you pull in. Maybe you can accomplish what you need without bringing in JQuery, modern browsers have excellent APIs built in these days. Aim for &lt;em&gt;progressive enhancement&lt;/em&gt; with JS. Your website should still work without JS turned on.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Regarding single page apps (SPAs), I genuinely believe too many people are making them. GMail is a web application and as such deserves a framework. Your blog platform? Not so much. Remember these frameworks not only put a lot of strain on user&#39;s experience, but it&#39;s also just &lt;em&gt;a lot to learn and maintain&lt;/em&gt;. Maybe your time could be served better.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;But my product owner says we need all these bells and whistles!&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;As a professional, it is up to you to take a stand. &lt;em&gt;You&lt;/em&gt; are the expert, not the customer.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You should be informing them how Amazon learned that every 100ms in page load cost them a 1% of sales.&lt;/li&gt;&#xA;&lt;li&gt;You should be informing them that making a carousel of their product catalogue is slow and annoying &lt;em&gt;and&lt;/em&gt; expensive to make compared to just listing them in a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;You should let them know that if they really want their groundbreaking poetry to reach around the world that they better make sure their website works on old hardware with slow Internet connections.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If I told the builder of my home to make it out of straw, I would hope she would convince me otherwise.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Of course, circumstances are tricky and sometimes people will ignore you but when you look at the state of some popular websites today you can only conclude that people either don&#39;t know what they&#39;re doing or are just not pushing back on bad requirements enough.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Take a look at the performance tab in developer tools for your website. Does it make you proud? If not, take some pride and start cutting away the cruft you thought you needed.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s take pride in making lean, accessible, simpler to execute websites by using simple technologies that work everywhere. There are moral and technical arguments for taking this approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that the goal of &lt;em&gt;most&lt;/em&gt; websites is &lt;strong&gt;delivering useful textual content, and all you &lt;em&gt;really&lt;/em&gt; need for that is HTML&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then we might not have to buy new laptops every 2 years and people less fortunate than you have a chance of actually using the web; the way it was intended.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 20 Aug 2018 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Why you should deploy on Friday afternoon</title>
      <link>https://quii.dev/Why_you_should_deploy_on_Friday_afternoon</link>
      <description>&lt;p&gt;I originally posted this at &lt;a href=&#34;https://dev.to/quii/why-you-should-deploy-on-friday-afternoon-285h&#34;&gt;Dev.to&lt;/a&gt; where lots of people agreed and disagreed.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Don&#39;t deploy on Friday afternoons!&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This expression is taken as programmer wisdom but I hate it. I&#39;m going to try and kill it, with words and experience.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The motivation behind it is sound. I don&#39;t want to spend my Friday nights debugging a production problem either.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;To me the expressions smacks of unprofessionalism. Software development as an industry has a poor reputation and phrases like this do not help.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you went to an ER on a Friday afternoon and was turned away because the doctors don&#39;t trust their own tools and know-how, how would you feel?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we want people to take our craft seriously we need to own it and not give the impression that we dont understand the systems are we making enough to make changes at the end of the week.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Why a lot of people don&#39;t want to deploy on Fridays&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;You don&#39;t understand your system&lt;/em&gt;. You&#39;re making changes but you&#39;re not 100% sure it&#39;ll be OK. Ask yourself why this is. Why are you scared of changing your software?&lt;/li&gt;&#xA;&lt;li&gt;Poor monitoring. If the users are the first to tell you if something is wrong, that feedback loop spills into time at the pub, rather than when you deploy.&lt;/li&gt;&#xA;&lt;li&gt;Overly-complicated rollback/branching. How is your disaster recovery? How easy is it to push a fix once you solve a bug?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Continuous Deployment/Delivery (CD)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I have worked on teams that have deployed new versions of various services in a distributed system multiple times at 4:30pm and not broke a sweat.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Why? Because deployment is fully automated and is a non-event. Here is the groundbreaking process.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write some code&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git commit -am &amp;quot;made the button pop&amp;quot;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git pull -r &amp;amp;&amp;amp; ./build &amp;amp;&amp;amp; git push&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Make a cup of tea&lt;/li&gt;&#xA;&lt;li&gt;It&#39;s now live.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Not so long ago it was considered normal for there to be releases every 6 months, or even just one at the end of a project.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The forward thinkers in that age saw problems with this&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Poor feedback loops&lt;/li&gt;&#xA;&lt;li&gt;Stressed development teams&lt;/li&gt;&#xA;&lt;li&gt;Catastrophic failures.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So the industry as a whole worked on lots of tooling, techniques and best practices to allow us to release software far quicker.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Recognising that releasing often reduces risk is generally accepted nowadays but teams still often settle on weekly or fortnightly releases; often matching the cadence of their sprints.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Which CD?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Annoyingly, continuous delivery and continuous deployment are very related concepts, with the same acronym; but refer to slightly different things:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;C Delivery means you&#39;ve set up your system so that software is very simple to deliver your software to users. Think pipelines, tests, automation e.t.c.&lt;/li&gt;&#xA;&lt;li&gt;C Deployment means if a commit is pushed to your main branch, and it passes all the checks, it is automatically deployed to live.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For the purpose of this post, when I say &amp;quot;CD&amp;quot; I mean &amp;quot;continuous deployment&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;What are the problems with weekly/fornightly releases?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The feedback loops are still not great. If you do your release there can be quite a lot of commits going live and if something is wrong it can be challenging to figure out exactly what broke. Especially if you wrote it 2 weeks ago.&lt;/li&gt;&#xA;&lt;li&gt;Still overly reliant on manual processes. I have seen teams actually skip a release because a QA was on holiday. This is surely unacceptable in 2018. Manual testing does not scale into the future. People leave, things get forgotten, etc.&lt;/li&gt;&#xA;&lt;li&gt;Let&#39;s you fall into the trap of writing stories that are dependant on other stories being finished in a &amp;quot;sprint&amp;quot;. When they aren&#39;t things can get very complicated.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;With CD we recognise that we can go further, deploying new software &lt;em&gt;to live&lt;/em&gt; every time the build is green. This has some amazing benefits,&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Extremely fast feedback loops. No longer do you have to think about code you wrote 2 weeks ago when there is a problem in live.&lt;/li&gt;&#xA;&lt;li&gt;Forces best practices. In order to be able to deploy to live on green you need excellent monitoring and tests. These are all &lt;em&gt;good things in their own right&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Reduces stress. &amp;quot;Releasing&amp;quot; is no longer a &lt;em&gt;thing&lt;/em&gt; any more. You can be confident in writing your software again!&lt;/li&gt;&#xA;&lt;li&gt;Vastly improves agility. Found a bug? Just fix it! This encourages a more lean way of working vs lots of upfront planning. There isn&#39;t even an option for a convoluted release process, &lt;strong&gt;you have to keep it simple&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Forces you to work on stories that are actually releasable. Not dependent on story x y and z. Forces the best practices on user stories that everyone acknowledges but often people ignore.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;But what if you break things?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Often people say with CD&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Yeah it&#39;s nice but what if it breaks? We should have a QA check things over&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&#39;s the thing, &lt;em&gt;no process in the world prevents bugs&lt;/em&gt;. You &lt;em&gt;will&lt;/em&gt; ship broken code. What&#39;s really important is how quickly you can detect and recover from it. Hoping manual testing will catch everything is wishful thinking.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How to CD on a new project&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It is much easier to do CD on a new project since you can start small and evolve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Generally your work should be centered on delivering the most valuable user journeys first, so this is an excellent chance to practice how to ensure that feature works without any humans checking anything.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write an end-to-end test. These are expensive to write and run and should only be reserved for your most important journeys&lt;/li&gt;&#xA;&lt;li&gt;Have monitoring with threshold alerts for when things go wrong&lt;/li&gt;&#xA;&lt;li&gt;Set up your pipeline so that when your code is pushed all the automated tests are run, if they pass go to production.&lt;/li&gt;&#xA;&lt;li&gt;Have some kind of green/blue release mechanism. Run your automated tests on the deployed release candidate and if they dont pass, dont ship it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;For each subsequent story ask yourself&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How will we know this is working? (monitoring)&lt;/li&gt;&#xA;&lt;li&gt;What tests do I need to have enough confidence this will work without any humans checking. Not every story needs a full end-to-end test on a huge distrubuted system but obviously you&#39;ll need some tests.&lt;/li&gt;&#xA;&lt;li&gt;Is this story as small as it can be? If your user stories are massive they are more likely to go wrong. If the story takes a week then that&#39;s back to slow feedback loops.&lt;/li&gt;&#xA;&lt;li&gt;If you cant answer these questions then you need to rethink the story. Notice these are all just basic agile principles for user stories. &lt;strong&gt;Continous delivery forces you to adhere to the principles that so often get ignored&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;How to CD on an existing project&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Peel away at the manual process&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You may have some kind of &amp;quot;run book&amp;quot; that is used when shipping the software. See what you could do to automate it.&lt;/li&gt;&#xA;&lt;li&gt;Find out all manual processes are happening. Ask why they are needed and what could be done to automate them.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;CD up to staging.&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Some companies have many environments in their delivery pipeline. A good first start is to automatically ship all the way up to the environment before live. A better step is remove as many of them as you can. It&#39;s ok to have some kind of &amp;quot;dev&amp;quot; environment to maybe experiment with but ask yourself why cant just test these things locally in the first place.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Identify a sub-system you could work with as a starting point&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;If you&#39;re working with a distributed system you might be able to identify a system which is easier to CD than the rest. Start with that because it&#39;ll give your team some insights into the new way of working and can help you begin to break the cultural barriers.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;CD is a cultural issue as much as a technical one&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Roles and responsibility&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Often a product owner or project manager wants to be the one who is in charge of releasing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There are circumstances where &lt;em&gt;exposing features to users&lt;/em&gt; should be controlled by a non-technical member of your team, but this can be managed with feature toggles.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But the copying of code from one computer to another is the responsibility of the developers on the team. After all we are the ones who are responsible for making sure the system works. &lt;strong&gt;It is a technical concern, not a business one.&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;What do QAs do now?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;CD is actually liberating for QAs&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Rather than spending their time manually testing poorly tested systems they can now focus on a more holistic view of the system, trying to facilitate an environment for CD so that the whole team can be confident things are working.&lt;/li&gt;&#xA;&lt;li&gt;QAs spend more effort helping developers define what needs to be tested and monitored for a story to be written.&lt;/li&gt;&#xA;&lt;li&gt;More time for exploratory testing&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Re-evaluate your tolerance for defects&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Lots of companies &lt;em&gt;think&lt;/em&gt; they cannot have any defects and will spend a lot of time and effort on complicated, time consuming (and therefore &lt;strong&gt;expensive&lt;/strong&gt;) processes to try and stop them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But think about the cost of all this? If you push a change to production that isn&#39;t covered by tests, perhaps a CSS change; consider if it&#39;s &lt;em&gt;really&lt;/em&gt; catastrophic if there&#39;s a small visual fault for some browsers&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe it is, in which case there are techniques to test specifically for this too.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Recovery&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Each release you do with CD will have the following qualities&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Plenty of tests&lt;/li&gt;&#xA;&lt;li&gt;Good monitoring&lt;/li&gt;&#xA;&lt;li&gt;Small scope&lt;/li&gt;&#xA;&lt;li&gt;Still &amp;quot;fresh&amp;quot; in the developer&#39;s mind&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;So in my experience fixing anything that falls through the cracks is easy. It&#39;s much less complicated than trying to look through 2 week&#39;s worth of git history.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would recommend in most cases not rolling back (unless it&#39;s really bad), but just fixing the issue and releasing it. Rollback is sometimes not an option anyway (e.g database migrations) so the fact that your system is geared to releasing quickly is actually a real strength of CD.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Other quick tips&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fast feedback loops are key. Measure your &lt;code&gt;git push&lt;/code&gt; to live time and keep it low.&lt;/li&gt;&#xA;&lt;li&gt;If things are getting slow re-evaluate your end-to-end tests. If you removed a test or refactored it to be a unit test, would you be any less confident? If not, then refactor away&lt;/li&gt;&#xA;&lt;li&gt;You may need to invest some time in making your components more testable to avoid writing lots of slow end-to-end tests. &lt;em&gt;This is a good thing&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Feature toggles are a useful tool but can become messy, keep an eye on the complexity&lt;/li&gt;&#xA;&lt;li&gt;Celebrate it. Moving from one release every 2 weeks to 50 a day feels great.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Wrapping up&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This has been a small introduction to CD, it&#39;s a huge topic with plenty of resources to investigate.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Continuous deployment is a big effort both technically and culturally, but it pays off massively.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have worked on distributed systems with over 30 separately deployable components with CD, and it has been less stressful than another project I&#39;ve worked on that had just a handful of systems but a ton of process and ceremony.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Being able to release software when it&#39;s written puts a higher emphasis on quality and reduces risk for the team. It also forces you into using agile best practices like testable, small, independently releasable user stories.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Maybe most importantly, it demands that you understand your system and that you&#39;re not deploying to production and crossing your fingers. That feels more professional to me.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 28 May 2018 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Tis the season to write Clojure</title>
      <link>https://quii.dev/Tis_the_season_to_write_Clojure</link>
      <description>&lt;p&gt;&lt;code&gt;[:fa (take 9 (repeat :la))]&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post is aimed at beginners who want to take a look at &lt;em&gt;Clojure&lt;/em&gt;, a super-interesting language which is probably quite different to what you’re used to.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You will learn some basic concepts and see how to write a Secret Santa assigner because &lt;em&gt;IT’S CHRISTMAS&lt;/em&gt;!!!!! :D&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Assumptions&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;You are somewhat familiar with programming, understand concepts like flow control (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;when&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, etc), variables, functions, &amp;amp; methods. If you’ve done a bit of Ruby or Javascript, you’ll probably be fine.&lt;/li&gt;&#xA;&lt;li&gt;Everything you do for this post will be done through the terminal, so it’s assumed you have some familiarity and confidence with it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;What is Clojure?&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A general purpose language like Java, Ruby, et al&lt;/li&gt;&#xA;&lt;li&gt;Can also compile to Javascript so you can use Clojure to write client-side code for your website as well as the backend; so you can write a rich website end-to-end with one language&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Getting started&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://leiningen.org/#install&#34;&gt;Here’s a link to install a tool called Leiningen&lt;/a&gt; which lets you easily create Clojure projects.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you’re on a Mac and have &lt;code&gt;homebrew&lt;/code&gt; installed you can just run &lt;code&gt;brew install leiningen&lt;/code&gt;. If you dont have homebrew installed, &lt;a href=&#34;https://brew.sh/&#34;&gt;you should install it&lt;/a&gt; as most useful coding tools are installed using it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Check your installation is working by typing &lt;code&gt;lein&lt;/code&gt; in your command line, you should see a load of blurb.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;The first time you run &lt;code&gt;lein&lt;/code&gt;it may take some download the stuff it needs. It won’t be that slow on subsequence runs.&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;If you see it complaining about JDK&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Clojure is compiled using the Java Development Kit which you might not have installed on your computer. On Mac you can use &lt;code&gt;brew&lt;/code&gt; to install it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;brew update &amp;amp;&amp;amp; brew cask install java&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Assuming it’s all working you can now type &lt;code&gt;lein repl&lt;/code&gt;, this is a great way just to experiment with Clojure as you can just type code and try it out.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The last line in the terminal should read something like &lt;code&gt;user =&amp;gt;&lt;/code&gt;. If you ever wish to quit the REPL just type &lt;code&gt;exit&lt;/code&gt; and hit return.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Type &lt;code&gt;(println &amp;quot;Hello, world&amp;quot;)&lt;/code&gt; and hit return and you should see&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;Hello, world&#xA;nil&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3&gt;What’s with the nil?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Every time you execute some Clojure like &lt;code&gt;(println &amp;quot;hello world&amp;quot;)&lt;/code&gt; it &lt;em&gt;will always return a value&lt;/em&gt;. They are called “expressions”. This is a strength of Clojure and adds to its simplicity via consistency.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Think about some functions you have called in other programming languages, sometimes they return a value and sometimes they don’t.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Given this Javascript&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;function myAdder(x, y) {&#xA;     x + y&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Oops no result! You forgot to put &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This approach results in Clojure being more terse, you don’t have to worry about explicitly returning, imagine how rubbish this would be &lt;code&gt;(return + 20 (return - 50 20)&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the case of &lt;code&gt;println&lt;/code&gt; it can’t return anything meaningful as it just prints to the screen so it return &lt;code&gt;nil&lt;/code&gt; which means “nothing”. The REPL always prints the result of the expression you run, so in the last case you see our &lt;code&gt;println&lt;/code&gt; being printed, and then the result of the expression being printed (&lt;code&gt;nil&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you try &lt;code&gt;(+ 20 50)&lt;/code&gt; you will see it just prints &lt;code&gt;=&amp;gt; 70&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;REPL tips&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Inside the REPL if you’re not sure what a function does type &lt;code&gt;(doc function-name)&lt;/code&gt; e.g &lt;code&gt;(doc println)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Often you can use tab to get auto-complete¡&lt;/li&gt;&#xA;&lt;li&gt;Press the up arrow key to cycle through previous expressions&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Clojure vs Javascript&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Here’s some examples of some common operations you’d do while writing an application in both Clojure and Javascript. Try out the Clojure examples in the REPL and get in the habit of using &lt;code&gt;doc&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Note the variety of syntax for doing these tasks in Javascript compared to Clojure.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This isn’t picking on Javascript in particular, this is true of most mainstream programming languages.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Adding&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Javascript: &lt;code&gt;1 + 1&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clojure &lt;code&gt;(+ 1 1)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Calling a function&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Javascript &lt;code&gt;alert(&#39;Chris&#39;)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clojure &lt;code&gt;(println &amp;quot;Chris&amp;quot;)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Flow control&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Javascript&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;if(CHRISTMAS){&#xA;    return “PUT NUTMEG IN EVERYTHING”&#xA;} else {&#xA;    return “PUT SORROW IN EVERYTHING”`&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Clojure&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(if :CHRISTMAS &amp;quot;PUT NUTMEG IN EVERYTHING&amp;quot; &amp;quot;PUT SORROW IN EVERYTHING&amp;quot;)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Doing stuff with lists&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Javascript&#xA;&lt;code&gt;[&amp;quot;chris&amp;quot;,&amp;quot;ruth&amp;quot;].foreach(name =&amp;gt; println(&#39;hello&#39; + name)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Clojure&#xA;&lt;code&gt;(doseq [name [&amp;quot;chris&amp;quot; &amp;quot;ruth&amp;quot;]] (println name))&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;How is Clojure different?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You should notice that the syntax for all of this stuff is the same&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(function argument1 argument2)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And you can build more complicated expressions, just like you do in maths by nesting.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(+ 20 (- 30 50))&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The inner expression gets evaluated leaving us with&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(+ 20 -20)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Which is &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Unlike in Javascript and most other mainstream languages where arguments and function names can appear in different orders and positions, you also need to know symbols like &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;=&amp;gt;&lt;/code&gt;. It’s no wonder learning programming is so difficult.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What I find the most interesting thing about Clojure is that the syntax is completely uniform. The barrier to entry to learning &lt;em&gt;how&lt;/em&gt; to write valid Clojure is very low. Writing &lt;em&gt;Clojure that actually works&lt;/em&gt; is still a challenge just like any other language, but the syntax is very easy to pick up.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An interesting side-effect of this approach is that you will come to understand that &lt;code&gt;the code in clojure is data&lt;/code&gt;. When you are constructing functions like &lt;code&gt;(+ 2 2)&lt;/code&gt; that is actually a &lt;em&gt;list&lt;/em&gt; of data, containing functions and arguments (just like a list of names like &lt;code&gt;(&amp;quot;chris&amp;quot; &amp;quot;ruth&amp;quot;)&lt;/code&gt;).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Accomplished clojure-ists use this to write &lt;em&gt;code that parses and manipulates code&lt;/em&gt; called “macros”. Try not to worry too hard about this right now, but it is a very interesting property of Clojure.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Secret Santa time&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now you probably feel like a Clojure expert so lets ship some epic code.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Values&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When you write code you generally need to store useful information in variables for later use. To do that in Clojure, there is no magic special syntax (as promised!) just call &lt;code&gt;def&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the REPL try &lt;code&gt;(def my-santas [&amp;quot;Chris&amp;quot; &amp;quot;Ruth&amp;quot; &amp;quot;Turner&amp;quot; &amp;quot;Hooch&amp;quot;])&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The only new syntax you’ve seen here is &lt;code&gt;[ ]&lt;/code&gt; which creates a data structure called a &lt;code&gt;Vector&lt;/code&gt; which for now you can just think of as an Array like in Ruby or JS.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you want to get to your variable, just type &lt;code&gt;my-santas&lt;/code&gt; into the REPL.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;How do you Secret Santa?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;We need some kind of algorithm to pair up people for Secret Santa. When thinking about this stuff it’s often helpful to think about how would you solve the problem in real life.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We need a way of representing in data people being paired up; &lt;code&gt;x gives to y, y gives to z&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;We need to randomise the people&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;How &lt;em&gt;I&lt;/em&gt; have done this is just one of many ways of doing Secret Santa. I fully encourage you to try different ways!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When tackling a problem you’re not sure about it’s always best to break the problem down into smaller and simpler chunks.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Representing our data&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;For a starting point, we need a way of representing our pairing up of Santas. The &lt;code&gt;map&lt;/code&gt; data type is perfect for this. If you’re unfamiliar, a map is a data structure like an Array but it has a set of keys with corresponding values.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They are called HashMaps in Ruby and Objects in Javascript. You can broadly think of them as dictionaries.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We can represent our result for Secret Santa in a map (syntax for maps are &lt;code&gt;{key1 value1, key2 value2}&lt;/code&gt;)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;{&amp;quot;chris&amp;quot; &amp;quot;ruth&amp;quot;, &amp;quot;ruth&amp;quot; &amp;quot;hooch&amp;quot;, &amp;quot;hooch&amp;quot; &amp;quot;turner&amp;quot;, &amp;quot;turner&amp;quot; &amp;quot;chris&amp;quot;}&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;i.e Chris gives to Ruth, Ruth gives to Hooch, etc..&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Creating our first representation&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;zipmap&lt;/code&gt; is a function in Clojure that takes two vectors and “zips” them into a map (funnily enough).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So try in the REPL &lt;code&gt;(zipmap my-santas my-santas)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You should get &lt;code&gt;{&amp;quot;Chris&amp;quot; &amp;quot;Chris&amp;quot;, &amp;quot;Ruth&amp;quot; &amp;quot;Ruth&amp;quot;, &amp;quot;Turner&amp;quot; &amp;quot;Turner&amp;quot;, &amp;quot;Hooch&amp;quot; &amp;quot;Hooch&amp;quot;}&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;OK, so everyone is just giving a gift to themselves but our basic data structure is there and we can see if we can just adjust the second argument to &lt;code&gt;zip-map&lt;/code&gt; in such a way that everyone is moved along one, it could work!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Try experimenting with &lt;code&gt;zipmap&lt;/code&gt;, what do you think happens with &lt;code&gt;(zipmap my-santas [1 2])&lt;/code&gt; ?&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Rotate the list&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;We don’t want Ruth give a gift to Ruth, if we can take our second copy of &lt;code&gt;my-santas&lt;/code&gt; and change it then everyone will give to someone different&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Imagine our room of Santas standing in a line&#xA;&lt;code&gt;Chris Ruth Turner Hooch&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then you clone them (like our &lt;code&gt;zipmap&lt;/code&gt; does)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Chris Ruth Turner Hooch&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Chris Ruth Turner Hooch&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If we just shifted the cloned row to the right, and put the person on the end back to the beginning…&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Chris Ruth Turner Hooch&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Hooch Chris Ruth Turner&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Everyone could take their gift and give it to the person in front of them and we would have our Secret Santas.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;How do we do that?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again, try and simplify the problem&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Make a new vector&lt;/li&gt;&#xA;&lt;li&gt;With the last one as the first item&lt;/li&gt;&#xA;&lt;li&gt;Then the rest on the end&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Clojure’s amazing standard lib again provides us with &lt;code&gt;last&lt;/code&gt; to get the last element of a vector and &lt;code&gt;butlast&lt;/code&gt; to get everything &lt;em&gt;apart&lt;/em&gt; from the last item. Along with the function &lt;code&gt;cons&lt;/code&gt; which lets us create new vectors let’s stick it all together.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In the spirit of breaking things down first try &lt;code&gt;(cons (last my-santas) (butlast my-santas))&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Then put it together&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(zipmap my-santas (cons (last my-santas) (butlast my-santas)))&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You’re allowed newlines to let the code breathe a bit&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(zipmap my-santas &#xA;         (cons (last my-santas) (butlast my-santas)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Which results in &lt;code&gt;{&amp;quot;Chris&amp;quot; &amp;quot;Hooch&amp;quot;, &amp;quot;Ruth&amp;quot; &amp;quot;Chris&amp;quot;, &amp;quot;Turner&amp;quot; &amp;quot;Ruth&amp;quot;, &amp;quot;Hooch&amp;quot; &amp;quot;Turner&amp;quot;}&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Awesome! Chris gives to Hooch, Ruth gives to Chris, etc.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Randomise&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;This is nice but it gives us the same result every time. We can make our algorithm even better by adding some randomisation.&lt;/p&gt;&#xA;&#xA;&lt;h5&gt;Shuffle&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;Try typing &lt;code&gt;(shuffle my-santas)&lt;/code&gt; in the REPL and you’ll see it takes a &lt;code&gt;Vector&lt;/code&gt; and shuffles it. This could be useful for us to make our expression a bit more exciting.&lt;/p&gt;&#xA;&#xA;&lt;h5&gt;Let&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;let&lt;/code&gt; is a function that allows you to declare values that can be used inside the function passed to it&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(let [x 1, y 2] (+ x y)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;(Remember this might look a bit weird but it still follows the convention of &lt;code&gt;(fn arg1 arg2)&lt;/code&gt;. It&#39;s just for &lt;code&gt;let&lt;/code&gt; its 1st argument is a vector, and then an expression to run)&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In Javascript it’s:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;x = 1&#xA;y = 2&#xA;return x + y&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The utility is the same, when writing non-trivial code you need to capture values and name them to improve readability. Coming back to our case we want to create a variable called &lt;code&gt;random-santas&lt;/code&gt; that stores our shuffled Santas for the rest of the code to use.&lt;/p&gt;&#xA;&#xA;&lt;h5&gt;Stick it all together&lt;/h5&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s use these functions to make our algorithm less predictable and store some values to let our code read easier.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;(let [random-santas (shuffle my-santas)&#xA;   shuffled-santas (cons (last random-santas) (butlast random-santas))]&#xA;   (zipmap random-santas shuffled-santas))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The code now reads relatively ok!&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Randomise the santas list&lt;/li&gt;&#xA;&lt;li&gt;Create a copy of that list called &lt;code&gt;shufled-santas&lt;/code&gt;, where everyone has moved to the right and we put the last Santa at the front&lt;/li&gt;&#xA;&lt;li&gt;zip them together to create our pairings of &lt;code&gt;Chris gives to Ruth&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Challenge for yourself&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What if you want to re-use our amazing algorithm with different sets of Santas?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You probably want to define a function, so you can use it just like we’ve used functions like &lt;code&gt;shuffle&lt;/code&gt; and &lt;code&gt;zipmap&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The basic syntax for defining your own function is&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(defn name-of-function [arg1, arg2, etc] function-body)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Example&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;(defn add-2 [number] (+ number 2))&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And then you can call it just like any other function &lt;code&gt;(add-2 10)&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Give it a go! Write &lt;code&gt;secret-santa&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;We saved Christmas!&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;That was probably a lot to take in but I hope it has been at least interesting. Maybe try to re-implement it yourself and see how far you get. Can you think of different ways to write it?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What might be more interesting is to implement the Secret Santa in a language you’re more familiar with. Think about how different your implementation is to the Clojure one, especially in regards to potentially all the different kinds of syntax you faced vs &lt;code&gt;(fun arg1 arg2)&lt;/code&gt;.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 02 Dec 2017 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Developers are stakeholders</title>
      <link>https://quii.dev/Developers_are_stakeholders</link>
      <description>&lt;p&gt;When it comes to prioritising work you may find yourself in an environment where it can feel hard to justify playing &amp;quot;technical&amp;quot; stories. These are stories raised by developers and typically cover&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Raising the quality of the code&lt;/li&gt;&#xA;&lt;li&gt;Fixing technical/architectural debt&lt;/li&gt;&#xA;&lt;li&gt;Addressing edge-cases&lt;/li&gt;&#xA;&lt;li&gt;Making the system easier to operate&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;The usual excuse for not playing this work is that a team should only ever be delivering &amp;quot;business value&amp;quot; but that is almost always defined as customer-facing features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At the same time developers will be responsible for making sure the system works, often obliged to be on call using their precious free time. This is a responsibility which is usually uniquely assigned to developers. You will rarely find a project manager being on call.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This isn&#39;t an issue of fairness, on a practical level it is unrealistic for anyone other than developers to fix most issues.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But given developers are responsible for not only delivering but also maintaining these systems &lt;strong&gt;it is only fair that they are also treated as stakeholders&lt;/strong&gt; and need to have a say on what non-shiny work is being done.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;But what if the developers spend all their time over-engineering everything?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;This is nothing more than a matter of trust. If you do not trust your developers to make pragmatic choices for delivering sustainable systems then you have big problems.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Presumably you are doing showcases every one or two weeks so it should become very clear quickly if your team isn&#39;t delivering stuff as fast as you like.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Why didn&#39;t they make it sustainable and reliable in the first place?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Remember that whole agile thing of &lt;code&gt;build-&amp;gt;measure-&amp;gt;learn&lt;/code&gt;? And the prime directive? It is unrealistic to expect all software to be perfect when it is first built. Only when you have shipped some code and seen it used do you really start to understand the flaws in the implementation.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you think you can just ignore the developers and entirely micromanage their time then they will resent the project and especially resent being woken up at 3am to fix a problem which they had anticipated but you didn&#39;t believe them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you value the following attributes of your system:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How easy it is to change&lt;/li&gt;&#xA;&lt;li&gt;How reliable it is&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Then you have to acknowledge that the work developers wish they could do has business value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So talk to your developers, trust and empower them.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 19 Jun 2017 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Testable Systems and Continuous Deployment</title>
      <link>https://quii.dev/Testable_Systems_and_Continuous_Deployment</link>
      <description>&lt;p&gt;People talk a lot about how to write testable code but &lt;em&gt;testable systems&lt;/em&gt; are what you need if you are going to be able to practice continous deployment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing testable systems takes practice and can be quite domain specific, but there are some general rules that you can apply.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may encounter resistance to making this extra effort so along with some guidance I will discuss how I justify this approach.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Some positive traits of a mature system&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Being able to improve the system without worrying about breaking it.&lt;/li&gt;&#xA;&lt;li&gt;Releasing features as soon as they&#39;re ready, not tied down to release schedules.&lt;/li&gt;&#xA;&lt;li&gt;Fast feedback loops, knowing when there are problems and being able to fix them quickly.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;What impedes a mature system from being fun to work with&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Lack of confidence in the system so lots of manual testing.&lt;/li&gt;&#xA;&lt;li&gt;This leads to fewer releases.&lt;/li&gt;&#xA;&lt;li&gt;Which leads to slower feedback loops which makes it harder to fix problems and you are slower in delivering value.&lt;/li&gt;&#xA;&lt;li&gt;Lack of confidence results in fear-driven development, where people become incredibly risk averse, taking decisions which are well intentioned but can end up complicating matters.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;So what do you need?&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Releasing as often as possible, preferably every commit to master is going to live.&lt;/li&gt;&#xA;&lt;li&gt;Absolutely no manual tests so you have &amp;quot;acceptance tests&amp;quot; running on each deployed component, including live and some end to end tests for some key scenarios.&lt;/li&gt;&#xA;&lt;li&gt;These tests are running periodically irrespective of releases so you know your system is working &lt;em&gt;in live&lt;/em&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Writing testable code can be more effort but it&#39;s worth it and the same is true for systems. With some effort you can make sure the project you&#39;re working on is pleasant to work with and you can actually start &lt;em&gt;looking forward to releases&lt;/em&gt; rather than worrying about whether it is going to work.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;&amp;quot;Just write a ticket and we&#39;ll let the product owner prioritise it later&amp;quot;&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In a common agile scrumban development environment where everything is focused on &amp;quot;business value&amp;quot;, &amp;quot;story points&amp;quot; you &lt;strong&gt;must assert that the development team are stakeholders too&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If your system is useful you will continue to work and maintain it so it&#39;s important to do work and add features which might not be for the direct benefit of the actual customer but help the development team.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Every job spec in the world talks about developers being empowered and responsible for the systems they create so make sure you call your company out. Fight for this if needs be otherwise you&#39;re going to have a miserable time.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Some rules to live by&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you are working on a new feature or system ask yourself&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;How can I be confident this will work that does not require me to manually test it in live?&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Then figure out these answers, the answers may not always be as straightforward as you hope but by putting yourself in this mindset you will write your system in a way that is testable from the start, rather than trying to retrofit it.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Involve your colleagues, in particular QAs as to how we can be sure that when the commit is merged that it will go to live and deliver high-quality value reliably&lt;br /&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Just like how you don&#39;t worry about breaking the internals of your system because of unit tests you also wont worry about deploying new versions of your system because everything is built with testing in mind.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like the tests within your system you should be striving for your tests to be reliable and fast to run.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If your tests are proving problematic and are being flaky then you should stop working on features until it is sorted.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Over recent years I have been working with this mindset and I am going to describe a number of techniques to help make your system testable&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Write good, testable well separated code&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;An obvious one but if you maintain good separation of concerns then it&#39;s much easier to &amp;quot;open up&amp;quot; your systems for tests.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Avoid the browser&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;For a web app you will need some tests in the browser but keep them to a minimum. Follow Fowler&#39;s test pyramid because otherwise you will have a slow, flaky test suite which becomes a big maintenance overhead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Good code design (separation of concerns especially) will allow you to test a lot of functionality without the need to run a web browser.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A trick I have learned to avoid web browsers but still test content that is being delivered is by adding some functionality to the web app so if you make a request with an &lt;code&gt;Accept&lt;/code&gt; header of &lt;code&gt;application/json&lt;/code&gt; it returns the view model representation as JSON rather than the rendered HTML. This allows you to test with simpler HTTP tools rather than firing up a browser which will be much faster to run and more reliable.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Idempotence&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When writing systems if you see an opportunity for an operation to be idempotent then go for it. This makes writing tests a lot simpler as you dont have to worry about the previous state of the system which is often a cause of complication when writing system tests.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Open up your system&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Your deployed system may get it&#39;s input from sources that are not as easily accessible as you&#39;d hope, for instance maybe a message queue or a file system on a secured server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is less easy to test than say a system that is interacted with over HTTP, with which there are tons of simple and quick tools to use.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;An option for this is to create an internal endpoint with an API that allows you to work with the system as if you are a file-system, message queue or whatever.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Not only does this make writing tests very easy but in my experience the QAs have found these endpoints invaluable for demos and exploratory testing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Good separation of concerns should make this relatively simple to accomplish but you may wish to employ some kind of &#39;isTest&#39; flag to let you separate out that from normal data if you need to.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;A more concrete example&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Recently I worked on a service that took its input from a message queue in the form of some JSON, perform some business logic on it and then put it onto another exchange for other parts of the system to consume.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The JSON is a payload which is to be rendered as a HTML email. It also calls some other services to help it create this payload.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Taking a very pedantic approach to developing this would&#39;ve resulted in a tricky system to write a test for in isolation. Obviously we had some unit tests with some fakes services wired up but we still didn&#39;t feel super confident.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thankfully the domain logic was really nicely separated out so we were able to expose the logic over HTTP so that you can &lt;code&gt;POST&lt;/code&gt; to the service and then get the rendered HTML back. Coupling this with PhantomJS we could take screengrabs of the rendered HTML and use image diffs to test for any regressions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The other benefit was the BA and QA could also use this endpoint to try it out with other datapoints very easily so they could demo it; and of course they found some bugs.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Code just for tests? Wtf&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yes, I&#39;ve read The Lean Startup too.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Again &lt;em&gt;developers are stakeholders&lt;/em&gt;. No one bats an eye when you write logging or metrics code, probably because it is not &amp;quot;seen&amp;quot; and it is perceived as low effort. In addition no one complains when you write unit tests (I hope) even though it&#39;s not directly aiding the customer.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Writing testable systems is often just an extension of this logic, everyone in the business should value the maintainability, extensibility, releasability and reliability of your system and these kind of measures facilitate these traits.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Straight to live? But what about bugs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;No process in the world will truly stop all bugs apart from very expensive means and 99% of developers don&#39;t need to produce bug free systems (despite what their product owners might like to think!)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Perfect is the enemy of good&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;However when you adopt these methods you are more likely to find bugs quicker but most importantly deploy a fix within potentially minutes rather than on some weekly release schedule.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Benefits for the QAs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;By automating away the manual testing process our QA now has more time for exploratory testing and the testing endpoints we add to our system helps facilitates this.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When it comes to starting a new piece of work the QA can come armed with a number of suggestions to help ensure the quality of the system; rather than spending their time re-testing software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have also found that QAs will spend more time thinking about the quality of the test suites and deployment process etc, making sure we as a team have quality for &lt;em&gt;the whole system&lt;/em&gt; rather than &lt;em&gt;just&lt;/em&gt; the end product.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;It&#39;s 2017: Do continuous deployment (for new projects at least)&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you have your tests in such a state that you are confident to release with every commit a tremendous burden is lifted from your team and it also pays off years down the line. How many times have you had to work with a &amp;quot;legacy&amp;quot; system where it&#39;s tough to even deploy the code in the first place and you have to spend hours doing manual tests.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;With CD not only are you guaranteeing that you can ship new changes when they are ready quickly but in a few years down the line when some poor sap has to work with your no longer flavour of the month programming language, they can at least be confident that they can make the necessary changes and get it shipped with little fuss.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you do encounter resistance then you are not working in an agile organisation. You are supposed to be in a position where you are empowered to improve processes and software to make delivering value as quick and as painless as possible. There is a difference between continuous &lt;em&gt;delivery&lt;/em&gt; and continous &lt;em&gt;deployment&lt;/em&gt;, the latter should not even be up for discussion. Deployments are the team&#39;s concerns, showing features to users is usually product owner&#39;s concern.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But still, if the company you work for are throwing terms like lean and agile around it should be in their interest to get features, even if they&#39;re imperfect infront of users as quickly as possible.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Tue, 21 Mar 2017 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Fun with Bash</title>
      <link>https://quii.dev/Fun_with_Bash</link>
      <description>&lt;p&gt;I was given a fairly mundane task at work and when this happens I try and find ways to make it interesting. I will usually find a way to learn something new to do the task so I can always get something out of the work I do, even if it&#39;s dull.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I would quite like to get better at using the legendary tools available to me on the command line. I have never felt &lt;em&gt;super&lt;/em&gt; confident doing text processing there, often giving up and just going to my editor instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am not going to exhaustively document every command I do, if you&#39;re curious about the details consult &lt;code&gt;man $command&lt;/code&gt; just like how I did! This post will just be illustrating how by doing a little research you can quickly do some rad text processing.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The task&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I am trying to analyse how much memory we are provisioning compared to actual usage for some of our services to see if our AWS bill can be cut down a bit.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I thought it would be fun (??) to use CSV, as it feels like CSV like data. Here is a sample of the data I captured.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&#xA;name, usage (mb), allocated (mb), CPU %, containers&#xA;dispatcher, 150, 512, 40, 10&#xA;assembler, 175, 512, 75, 10&#xA;matcher, 85, 512, 15, 10&#xA;user-profile, 128, 512, 40, 5&#xA;profile-search, 220, 512, 80, 10&#xA;reporter, 90, 512, 40, 10 &#xA;mailgun-listener, 90, 512, 10, 5&#xA;unsubscribe, 64, 512, 3, 5&#xA;bounce, 8, 128, 0.5, 3&#xA;legacy-reporting, 30, 512, 15, 3&#xA;content-store, 80, 256, 30, 10&#xA;legacy-alert-poller, 64, 256, 1, 1&#xA;migrator, 80, 256, 10, 5&#xA;entitlements-update, 150, 256, 70, 3&#xA;&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;Display it nice&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is nice and easy &lt;code&gt;column -s, -t &amp;lt; data.csv&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;-t&lt;/code&gt; determines the number of columns the input contains and combined with &lt;code&gt;-s&lt;/code&gt; specifies a set of characters to delimit by. If you dont specify a &lt;code&gt;-s&lt;/code&gt; it defaults to using space.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&#xA;name                  usage (mb)   allocated (mb)   CPU %   containers&#xA;dispatcher            150          512              40      10&#xA;assembler             175          512              75      10&#xA;matcher               85           512              15      10&#xA;user-profile          128          512              40      5&#xA;profile-search        220          512              80      10&#xA;reporter              90           512              40      10 &#xA;mailgun-listener      90           512              10      5&#xA;unsubscribe           64           512              3       5&#xA;bounce                8            128              0.5     3&#xA;legacy-reporting      30           512              15      3&#xA;content-store         80           256              30      10&#xA;legacy-alert-poller   64           256              1       1&#xA;migrator              80           256              10      5&#xA;entitlements-update   150          256              70      3&#xA;&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;Sorting by usage&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;cat data.csv | sort -n --field-separator=&#39;,&#39; --key=2 | column -s, -t&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&#xA;name                  usage (mb)   allocated (mb)   CPU %   containers&#xA;bounce                8            128              0.5     3&#xA;legacy-reporting      30           512              15      3&#xA;legacy-alert-poller   64           256              1       1&#xA;unsubscribe           64           512              3       5&#xA;content-store         80           256              30      10&#xA;migrator              80           256              10      5&#xA;matcher               85           512              15      10&#xA;mailgun-listener      90           512              10      5&#xA;reporter              90           512              40      10 &#xA;user-profile          128          512              40      5&#xA;dispatcher            150          512              40      10&#xA;entitlements-update   150          256              70      3&#xA;assembler             175          512              75      10&#xA;profile-search        220          512              80      10&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;--key=2&lt;/code&gt; means sort by the second column&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Using awk to figure out the memory differences&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What we&#39;re really interested in is the difference between the amount of memory provisioned vs usage.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;awk -F , &#39;{print $1, $3-$2}&#39; data.csv&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s pipe that into column again&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;awk -F , &#39;{print $1, $3-$2}&#39; data.csv | column -t&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&#xA;name                 0&#xA;dispatcher           362&#xA;assembler            337&#xA;matcher              427&#xA;user-profile         384&#xA;profile-search       292&#xA;reporter             422&#xA;mailgun-listener     422&#xA;unsubscribe          448&#xA;bounce               120&#xA;legacy-reporting     482&#xA;content-store        176&#xA;legacy-alert-poller  192&#xA;migrator             176&#xA;entitlements-update  106&#xA;&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This is nice but it would be good to ignore the first line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;awk -F , &#39;{print $1, $3-$2}&#39; data.csv | tail -n +2&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;tail -n X&lt;/code&gt; prints the last &lt;code&gt;X&lt;/code&gt; lines, the plus inverts it so its the first &lt;code&gt;X&lt;/code&gt; lines.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Sort mk 2&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Now we have some memory differences it would be handy to sort them so we can address the most inefficient configurations first&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;awk -F , &#39;{print $1, $3-$2}&#39; data.csv | tail -n +2 | sort -r -n --key=2&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;And of course use column again to make it look pretty&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;awk -F , &#39;{print $1, $3-$2}&#39; data.csv | tail -n +2 | sort -r -n --key=2 | column -t&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&#xA;legacy-reporting     482&#xA;unsubscribe          448&#xA;matcher              427&#xA;reporter             422&#xA;mailgun-listener     422&#xA;user-profile         384&#xA;dispatcher           362&#xA;assembler            337&#xA;profile-search       292&#xA;legacy-alert-poller  192&#xA;migrator             176&#xA;content-store        176&#xA;bounce               120&#xA;entitlements-update  106&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;WTF&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There it is! The utterly indecipherable bash command that someone reads 6 months later and scratches their head. In fact there has been 2 weeks since I wrote the first draft of this and I look at the final command and weep.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is very easy to throw up your hands when you see a shell script that doesn&#39;t make sense but there are things you can do.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Remember that the process will usually start small like we have here, starting with one command, piping it into another, into another. This gives the lazy dev like me the perception that it is a complicated command but all it really is a set of steps to process some data. So if you&#39;re struggling you can wind back some of the steps for yourself by just deleting some of the steps and see what happens.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If it is an important business process that needs to be understood for a long time, you&#39;re probably better off writing it in a language where you can write some automated tests around it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But a lot of the work we do does involve doing things that are ad-hoc and doesn&#39;t reside in &amp;quot;the codebase&amp;quot; where you can easily get into a TDD rhythm to accomplish something shiny.  Often you have to do something a little boring and sometimes the tools available on your computer can really help you out. They&#39;re so old and well established that you can find tons of documentation and tips so dive in!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you need more reasons to get to know the shell better read how &lt;a href=&#34;https://aadrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html&#34;&gt;command line tools can be up to 235x faster than your hadoop cluster&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 20 Mar 2017 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Testing Asynchronous Code In Go</title>
      <link>https://quii.dev/Testing_Asynchronous_Code_In_Go</link>
      <description>&lt;p&gt;Sometimes you may need to test that an asynchronous event has been triggered in&#xA;your code but you can end up compromising on the quality of your tests when&#xA;doing so.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post will show one technique to test this behaviour whilst keeping your tests clean and not complicating your production code&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It&#39;s assumed you&#39;re familiar with writing tests, interfaces, go routines, channels and &lt;code&gt;select&lt;/code&gt; from Go.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The code to test&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We are writing a service which has a dependency of a repo passed to it. Plain and simple DI for separation of concerns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The service has a method &lt;code&gt;FaveAndSave&lt;/code&gt; which takes a &lt;code&gt;string&lt;/code&gt; and it will do some amazing business logic and then save to the repo.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type Repo interface {&#xA;    Save(string)&#xA;}&#xA;&#xA;type Service struct {&#xA;    repo Repo&#xA;}&#xA;&#xA;// FaveAndSave does something great with your string and saves it&#xA;func (s Service) FaveAndSave(x string) {&#xA;    go s.repo.Save(&amp;quot;☆&amp;quot; + x)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The code calls the &lt;code&gt;repo&lt;/code&gt; in a new go routine which makes testing a little tricky.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Let&#39;s test it&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The benefit of using DI here is that we can now stub our &lt;code&gt;Repo&lt;/code&gt;, make it behave how we like and see how it&#39;s called.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type repoStub struct{&#xA;    saveCalled bool&#xA;}&#xA;&#xA;func (s *repoStub) Save(x string) {&#xA;    s.saveCalled = true&#xA;}&#xA;&#xA;func TestItTriggersSave(t *testing.T) {&#xA;    repo := new(repoStub)&#xA;    service := Service{repo}&#xA;&#xA;    service.FaveAndSave(&amp;quot;Cat&amp;quot;)&#xA;&#xA;    if !repo.saveCalled {&#xA;        t.Error(&amp;quot;Save was not called&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This test fails wrongly because the save event is fired off in a separate go routine&#xA;which ends up being executed &lt;em&gt;after&lt;/em&gt; our assertion.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means the &lt;code&gt;saveCalled&lt;/code&gt; value is still set to &lt;code&gt;false&lt;/code&gt; when we make our assertions.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Solution 1 - Sleepy time&lt;/h2&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestItTriggersSave(t *testing.T) {&#xA;    repo := new(repoStub)&#xA;    service := Service{repo}&#xA;&#xA;    service.FaveAndSave(&amp;quot;Cat&amp;quot;)&#xA;&#xA;    time.Sleep(10 * time.Millisecond)&#xA;&#xA;    if !repo.saveCalled {&#xA;        t.Error(&amp;quot;Save was not called&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We can add a sleep into our test to let the go routine finish&#xA;before making assertions. But there are a few problems:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The sleep length I put in is fairly arbitrary and it&#39;s hard to know precisely what value it should be. You dont want to set it to be too long because then your test will be slow, but too short will make the test flaky.&lt;/li&gt;&#xA;&lt;li&gt;It&#39;s noise in our test. In this simple example it doesn&#39;t seem so bad but it is ultimately more cruft which we need to try and avoid.&lt;/li&gt;&#xA;&lt;li&gt;Sleeps always feel yucky!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Solution 2 - Use a channel in our stubs&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We can embrace the asynchronousness of our production code so we dont have to rely on guessing how long the stub takes to get called.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type repoStub struct{&#xA;    saveCalled chan bool&#xA;}&#xA;&#xA;func newRepoStub() *repoStub {&#xA;    s := new(repoStub)&#xA;    s.saveCalled = make(chan bool)&#xA;    return s&#xA;}&#xA;&#xA;func (s *repoStub) Save(x string) {&#xA;    s.saveCalled &amp;lt;- true&#xA;}&#xA;&#xA;func TestItTriggersSave(t *testing.T) {&#xA;    repo := newRepoStub()&#xA;    service := Service{repo}&#xA;&#xA;    service.FaveAndSave(&amp;quot;Cat&amp;quot;)&#xA;&#xA;    if saved := &amp;lt;- repo.saveCalled; !saved {&#xA;        t.Error(&amp;quot;Save was not called&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Rather than setting a normal value we have a channel which gets written to when&#xA;the stub is called. This means our test can wait on a value to appear on the&#xA;channel, rather than using sleeps and hoping the value gets set.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This too has problems:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If the stub isn&#39;t called like we expect then the test will fail, but because of&#xA;deadlock/test time out.&#xA;This means our test output is less helpful then it should be.&lt;/li&gt;&#xA;&lt;li&gt;The test now has channels and general asynchronous behaviour which is&#xA;implementation detail that we dont really need to care about, like the sleeps it&#xA;is noise.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Solution 3 - Make the stub&#39;s value &amp;quot;blocking&amp;quot; with a timeout&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It seems these days many developers automatically recoil in disgust when you say &amp;quot;blocking&amp;quot; but it can often be simpler than the alternative.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I write a lot of Javascript in my day job and 99% of tests are littered with &lt;code&gt;promise&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt; and generally a lot of asynchronous cruft because &lt;em&gt;everything&lt;/em&gt; is asynchronous.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That can make writing tests quite taxing, especially if you are new to it. Common gotchas include tests not actually running assertions or tests running forever.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let&#39;s keep our tests clean by putting just a little bit of code in to our stubs to make them block for the event we care about&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type repoStub struct{&#xA;    saveCalled chan bool&#xA;}&#xA;&#xA;func newRepoStub() *repoStub {&#xA;    s := new(repoStub)&#xA;    s.saveCalled = make(chan bool)&#xA;    return s&#xA;}&#xA;&#xA;func (s *repoStub) Save(x string) {&#xA;    s.saveCalled &amp;lt;- true&#xA;}&#xA;&#xA;func (s *repoStub) WasSaveCalled() bool {&#xA;    select {&#xA;    case &amp;lt;-s.saveCalled:&#xA;        return true&#xA;    case &amp;lt;- time.After(1 * time.Second):&#xA;        return false&#xA;    }&#xA;}&#xA;&#xA;func TestItTriggersSave(t *testing.T) {&#xA;    repo := newRepoStub()&#xA;    service := Service{repo}&#xA;&#xA;    service.FaveAndSave(&amp;quot;Cat&amp;quot;)&#xA;&#xA;    if !repo.WasSaveCalled() {&#xA;        t.Error(&amp;quot;Save was not called&amp;quot;)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We have moved the responsibility of &amp;quot;&lt;em&gt;Has the stub been called in a timely manner?&amp;quot;&lt;/em&gt; to the stub &lt;em&gt;rather&lt;/em&gt; than the test by simply adding the method &lt;code&gt;WasSaveCalled&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The code takes advantage of Go&#39;s &lt;code&gt;select&lt;/code&gt; syntax to block until the value is written or until the timeout occurs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This feels like a good separation of concerns. Now if we look at the actual test we can see it reads very clearly and has no cruft around go routines or channels.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The code in the stub &lt;em&gt;maybe&lt;/em&gt; looks a little involved but you will definitely move these into separate files, perhaps even &lt;code&gt;go generate&lt;/code&gt; can be used to auto generate them like &lt;a href=&#34;https://github.com/ernesto-jimenez/goautomock&#34;&gt;goautomock&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This post was motivated by some work I am doing where we are writing&#xA;a &amp;quot;listener&amp;quot; to a RabbitMQ channel. The listener takes a &lt;code&gt;chan Message&lt;/code&gt;, gets&#xA;fired off in a go routine and processes messages as they come in to the system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We went through similar iterations described above until we arrived at solution&#xA;3.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Is this idiomatic Go? I&#39;m not sure I know what idiomatic Go is yet but this&#xA;solution to me ticks a number of boxes I care about in writing software irrespective of the programming language.&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Easy to read and write test code&lt;/li&gt;&#xA;&lt;li&gt;Separation of concerns in regards to &amp;quot;has this function been called?&amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;Good test output on failure&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Hopefully this has been interesting. Know a better way? Flame me on twitter &lt;a href=&#34;https://twitter.com/quii&#34;&gt;@quii&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Footnotes&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;For the sake of terseness this example just sees if &lt;code&gt;Repo&lt;/code&gt; is called, but you can of course see what it was called with. In the real world &lt;code&gt;Repo&lt;/code&gt; would probably have return values that we&#39;d stub for tests too.&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;I like to pass &lt;code&gt;t.Log&lt;/code&gt; to my stubs so they can log diagnostic info (such as &amp;quot;I timed out waiting for &lt;code&gt;x&lt;/code&gt;&amp;quot;), it has the added bonus they only appear if the test fails&lt;/em&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Thu, 29 Dec 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Property-based testing in real life</title>
      <link>https://quii.dev/Property-based_testing_in_real_life</link>
      <description>&lt;p&gt;Most property-based test examples you see on the web are contrived scenarios and people can be dismissive of them, claiming that they aren&#39;t actually practical. This post will have a simple example applied to one of my projects which will hopefully illustrate their value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a follow up to &lt;a href=&#34;/Property-based%20testing%20in%20Go&#34;&gt;Property-based testing in Go&lt;/a&gt; and if you&#39;re not familiar with these kind of tests I suggest you read that first, it&#39;s a quick read.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Although the examples are in Go there are &lt;a href=&#34;https://en.wikipedia.org/wiki/QuickCheck&#34;&gt;QuickCheck&lt;/a&gt; frameworks for most mainstream programming languages and the concepts described here will still apply.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post will:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Briefly explain the domain&lt;/li&gt;&#xA;&lt;li&gt;Describe writing a real world property-based test&lt;/li&gt;&#xA;&lt;li&gt;Summarise my conclusions&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;mockingjay server&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;It&#39;s important to have a good knowledge of the domain when writing property-based-tests, the following is an overview of the domain we will be testing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/mockingjay-server&#34;&gt;mockingjay-server&lt;/a&gt; (MJ) is an application which is a lightweight HTTP server driven from configuration.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;---&#xA; - name: My very important integration point&#xA;   request:&#xA;     uri: /hello&#xA;     method: POST&#xA;     body: Chris&#xA;   response:&#xA;     code: 200&#xA;     body: &#39;{&amp;quot;message&amp;quot;: &amp;quot;hello, Chris&amp;quot;}&#39;&#xA;     headers:&#xA;       content-type: application/json&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;MJ has two &amp;quot;modes&amp;quot;:&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Server mode&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Serves responses matched to requests that you define.&lt;/p&gt;&#xA;&#xA;&lt;h4&gt;Compatibility or &lt;a href=&#34;http://martinfowler.com/articles/consumerDrivenContracts.html&#34;&gt;CDC&lt;/a&gt; mode&lt;/h4&gt;&#xA;&#xA;&lt;p&gt;Take that same config, executing each request against a given URL and checking the response is compatible with the response in configuration. This is known as a &lt;em&gt;consumer-driven contract&lt;/em&gt; (CDC).&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Why?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;When writing integration tests against a HTTP service you will usually make a fake server (or some kind of stub around HTTP) to write tests against. You will then make your tests pass and be happy right?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fakes dont always correspond with the real behaviour&lt;/li&gt;&#xA;&lt;li&gt;Fakes might behave correctly at first, but if the downstream service changes the fake could be wrong&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;In both of these situations your build would be green but your software is broken.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;mockingjay allows you to make a server and easily verify that it is equivalent to what you&#39;re testing against. You can then distribute this configuration as a CDC for the maintainer of the downstream service, so they dont accidentally break the service for your use case. &lt;a href=&#34;https://github.com/quii/mockingjay-server/wiki/Rationale&#34;&gt;The wiki goes into this more&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;There is an inherent coupling between HTTP integration tests and consumer driven contracts. MJ leverages this in a single config.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;h2&gt;A property of mockingjay&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To write a property-based test we need to identify a property to throw lots of auto-generated data at, to make sure the property holds true.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A property of MJ is:&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;MJ should always be compatible with itself&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Here&#39;s my thinking:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Given&lt;/strong&gt; Config &lt;em&gt;A&lt;/em&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;When&lt;/strong&gt; You start an MJ server with config &lt;em&gt;A&lt;/em&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;And&lt;/strong&gt; you run a CDC check using config &lt;em&gt;A&lt;/em&gt; with the URL of the running MJ server&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Then&lt;/strong&gt; the CDC check should pass&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;If it doesn&#39;t it either means there is a flaw in the CDC algorithm or in the way the server is behaving.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have lots of example based tests for this but if I invest time writing a property-based test I can be really confident MJ is working.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Create a generator&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For all but the basic types you will need to create a &lt;code&gt;Generate&lt;/code&gt; method for the input type in your test. This will allow the &lt;code&gt;quickcheck&lt;/code&gt; package to create thousands of different data points to check the property against.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I made a simple one to start with and other HTTP things like headers, forms, etc can be added later.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func (r FakeEndpoint) Generate(rand *rand.Rand, size int) reflect.Value {&#xA;    randomMethod := httpMethods[rand.Intn(len(httpMethods))]&#xA;&#xA;    req := Request{&#xA;        Method: randomMethod,&#xA;        URI:    &amp;quot;/&amp;quot; + randomURL(rand.Intn(maxURLLen)),&#xA;    }&#xA;&#xA;    res := response{&#xA;        Code: rand.Intn(599-100) + 100,&#xA;    }&#xA;&#xA;    return reflect.ValueOf(FakeEndpoint{&#xA;        Name:     &amp;quot;Generated&amp;quot;,&#xA;        Request:  req,&#xA;        Response: res,&#xA;    })&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;FakeEndpoint&lt;/code&gt; is a representation of the config from earlier.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Test the property&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Write a function which takes the randomly generated endpoint&lt;/li&gt;&#xA;&lt;li&gt;Start an MJ server using that endpoint&lt;/li&gt;&#xA;&lt;li&gt;Take the same config and run the CDC against the server&lt;/li&gt;&#xA;&lt;li&gt;If there are any errors then the check fails&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Here&#39;s what the test looks like&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestItIsAlwaysCompatibleWithItself(t *testing.T) {&#xA;&#xA;    compatabilityChecker := NewCompatabilityChecker(noopLogger, httpTimeout)&#xA;&#xA;    assertion := func(endpoint FakeEndpoint) bool {&#xA;&#xA;        // Start an MJ server with the random configuration&#xA;        mjSvr := NewServer([]FakeEndpoint{endpoint}, false, ioutil.Discard)&#xA;        svr := httptest.NewServer(http.HandlerFunc(mjSvr.ServeHTTP))&#xA;        defer svr.Close()&#xA;&#xA;        // Run CDC against &amp;quot;itself&amp;quot;. An MJ server should always be compatible with itself.&#xA;        errors := compatabilityChecker.check(&amp;amp;endpoint, svr.URL)&#xA;&#xA;        if len(errors) &amp;gt; 0 {&#xA;            t.Log(&amp;quot;It wasn&#39;t compatible with itself&amp;quot;)&#xA;            for _, err := range errors {&#xA;                t.Log(err)&#xA;            }&#xA;        }&#xA;&#xA;        return len(errors) == 0&#xA;    }&#xA;&#xA;    config := quick.Config{&#xA;        MaxCount:1000,&#xA;    }&#xA;&#xA;    if err := quick.Check(assertion, &amp;amp;config); err != nil {&#xA;        t.Error(err)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When I ran the test I was pleasantly surprised in that the CDC check &lt;em&gt;failed&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;Couldn&#39;t reach real server: Post http://127.0.0.1:41006/snipped-really-long-random-url: 303 response missing Location header&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This means the CDC tried to POST to the configured URL and Go&#39;s HTTP client returned an error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is quite exciting, I haven&#39;t seen MJ configured with any 3xx response codes so this points to some naivety in my code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;HTTP 303 is &amp;quot;See other&amp;quot; which relies on a location header to get redirected to another resource.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Investigating Go&#39;s HTTP client&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Before writing any code for this I wanted to have a look at the Go source of &lt;a href=&#34;https://golang.org/src/net/http/client.go?s=6486:6538#L171&#34;&gt;&lt;code&gt;http.Client&lt;/code&gt;&lt;/a&gt; to see exactly how it works.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By following a few of the function calls we can see if it&#39;s a &lt;code&gt;POST&lt;/code&gt; or a &lt;code&gt;PUT&lt;/code&gt; and the status is a HTTP &lt;code&gt;Found 302&lt;/code&gt; or &lt;code&gt;See Other 303&lt;/code&gt; then it will expect a location header that it can parse with &lt;code&gt;req.URL.Parse&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I will have to add some additional validation to the configuration so that these rules can be respected &lt;em&gt;or&lt;/em&gt; make Go&#39;s HTTP client not follow redirects.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Conclusions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The costs of writing property-based tests are low (this took me about 10 minutes) and can help give you a lot of confidence in your code (or not!).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;What&#39;s great is that even on a very simple generator implementation the tests uncovered some bugs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This style of testing can:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Improve knowledge of the problem domain&lt;/li&gt;&#xA;&lt;li&gt;Find bugs you wouldn&#39;t have thought of otherwise&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;These things prove that property-based tests can improve the quality of your software.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Footnotes&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Other examples of this style of testing in the real world:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://skillsmatter.com/skillscasts/4505-quickchecking-riak&#34;&gt;QuickChecking Riak&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;In this talk John Hughes shows us how QuickCheck helped us to model Riak’s behaviour, improving understanding and revealing the occasional bug.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=zi0rHwfiX1Q&#34;&gt;John Hughes - Testing the hard stuff and staying sane&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Taking 3k lines of specification to create 20 lines of QuickCheck to test &lt;strong&gt;1 million&lt;/strong&gt; lines of code from 6 different vendors. Some real war stories in this video.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 27 Aug 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Magic</title>
      <link>https://quii.dev/Magic</link>
      <description>&lt;p&gt;Magic is often used to describe confusing code. Often we cannot explain how something works so magic seems like an apt description.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The problem with magic is that it’s an entirely subjective term which can be used as a very annoying stick to hit useful abstractions.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;An anecdote&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A while ago I wrote something along the lines of this in Scala.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;val transformedCollection = collection map transformer&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For those not familiar with the &lt;code&gt;map&lt;/code&gt; construct, this will run the &lt;code&gt;transformer&lt;/code&gt; function on each item in the &lt;code&gt;collection&lt;/code&gt;, returning a new collection of transformed items.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Another nameless programmer chastised me&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;quot;I like to be pragmatic&amp;quot;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;(Who exactly &lt;em&gt;doesn’t&lt;/em&gt; like to be pragmatic?)&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&amp;quot;This is magic, why not just write a for-loop, it’s clearer&amp;quot;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;Apart from the pragmatic comment it’s actually a reasonable thing to say, if you don’t understand how something works then it’s magical!&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Understand the magic&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Just because something seems magical doesn’t mean it’s wrong. The problem with the term is it’s often lazily used when someone doesn’t understand an abstraction, or worse - doesn’t &lt;em&gt;want&lt;/em&gt; to understand.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;So what is magic?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For me I get the feeling of dark arts surrounding me when there is a lack of explicitness. Generally stuff changing “underneath” me based on some kind of state of the system. It often feels like the code is working by accident rather than deliberately.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Anti-patterns like global imports and setter-based DI makes the system feel magical in a very ugly way.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Choose your spells&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;From time to time all of us look at some code and throw our hands up in the air when we don’t initially understand something. Rather than unsheathing our anti-magic sticks make an attempt to understand it first.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There’s nothing more annoying than someone describing your code as magic when you feel you put some effort into a useful abstraction. So try to be considerate when faced with unfamiliar constructs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That being said it is important for programmers to share their knowledge when introducing something new. Be sure to explain your sleight of hand at code review and use abstractions tastefully and keep intent clear at all times.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;tl;dr&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Don&#39;t lazily conflate the unfamiliar with magic. It&#39;s short-sighted and annoying.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 25 Mar 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Property-based testing in Go</title>
      <link>https://quii.dev/Property-based_testing_in_Go</link>
      <description>&lt;p&gt;This posts hopes to illustrate&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What property based testing is and why it is an important tool to compliment your existing tests&lt;/li&gt;&#xA;&lt;li&gt;How easy it is in Go&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Your current tests&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The usual examples illustrating TDD could be described as &lt;em&gt;example&lt;/em&gt; based tests; where you write tests by providing example inputs and expected outputs.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestAddingExample(t *testing.T) {&#xA;    result := add(3, 2)&#xA;    if result != 5 {&#xA;        t.Error(&amp;quot;3 plus 2 is 5 but i got&amp;quot;, result)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;When you realise that they are &lt;strong&gt;just&lt;/strong&gt; examples, you see your code perhaps isn’t as well-tested as you think.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Wouldn&#39;t it be nice if it were easy to provide &lt;strong&gt;thousands&lt;/strong&gt; of different test inputs for your tests?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may have already heard about property-based testing and think its about testing your code with randomly generated data to exercise different scenarios; but it actually requires a shift in mindset to get the most out of it.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Specifications, not just lots of data&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Property-based testing is called that because in order to write the tests you have to think about the &lt;em&gt;properties&lt;/em&gt; of your domain in order to write effective tests.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; An example with addition&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We will test an add function, which just adds 2 integers together.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func add(x, y int) int {&#xA;    return x + y&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The tricky thing when you feed in random data, is how do you know what your expected result should be?&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestAddition(t *testing.T){&#xA;  x := getRandomInt()&#xA;  y := getRandomInt()&#xA;&#xA;  expected := x + y&#xA;&#xA;  if expected != add(x, y){&#xA;    // oh no..&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You may be tempted to do the above, but in effect you’re cheating because you’re using the implementation to verify itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Pretend that you’re testing a more complicated function. You know you shouldn’t do the following:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestComplicatedThing(t *testing.T){&#xA;  x := getRandomInt()&#xA;  y := getRandomInt()&#xA;&#xA;  expected := complicated(x, y)&#xA;&#xA;  if expected != complicated(x, y){&#xA;    // oh no..&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This isn’t really testing anything, if you change the implementation of &lt;code&gt;complicated&lt;/code&gt; it will continue to pass its tests even if its behaviour is incorrect.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;(This is a common problem with bad tests where the writer has re-implemented the unit they are testing, in the test!)&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But what do you do? How can you verify your function on random inputs?&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The properties of addition&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;What &lt;em&gt;is&lt;/em&gt; there to addition anyway? Well, there’s a few things:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;when you add zero to a number, you get the same number back again&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;the order of the inputs does not matter&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Let’s write some property based tests based on these laws of addition.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func TestAddingZeroMakesNoDifference(t *testing.T) {&#xA;    /*&#xA;    Create an assertion, which is a function that takes N inputs of&#xA;    random data and returns true if the assertion passes. &#xA;&#xA;    In this case, we&#39;re saying take any random integer (x)&#xA;    If you add 0, it should equal x&#xA;    */&#xA;    assertion := func(x int) bool {&#xA;        return add(x, 0) == x&#xA;    }&#xA;&#xA;    // Run the assertion through the quick checker&#xA;    if err := quick.Check(assertion, nil); err != nil {&#xA;        t.Error(err)&#xA;    }&#xA;}&#xA;&#xA;func TestAssociativity(t *testing.T) {&#xA;    assertion := func(x, y, z int) bool {&#xA;        return add(add(x, y), z) == add(add(z, y), x)&#xA;    }&#xA;&#xA;    if err := quick.Check(assertion, nil); err != nil {&#xA;        t.Error(err)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The &lt;code&gt;quick.Check&lt;/code&gt; function will run your assertion 100 times (by default), feeding in randomly generated data for the inputs required. If it fails at any point then you will be told for what inputs your function fails on so you can go reproduce it and fix.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Notice how:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;By asserting on &lt;em&gt;properties&lt;/em&gt; rather than known values we don’t have to &amp;quot;cheat&amp;quot; on the tests like I did earlier.&lt;/li&gt;&#xA;&lt;li&gt;We have now described &lt;strong&gt;what addition is in terms of its properties&lt;/strong&gt;, which is more &lt;em&gt;expressive&lt;/em&gt; than the example based test from earlier.&lt;/li&gt;&#xA;&lt;li&gt;We now have a more robust test suite, able to run thousands of different inputs in milliseconds.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Thinking abstractly about your domain&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Once you take a step back and &lt;em&gt;really&lt;/em&gt; think about the domain of your code, you may discover some unexpected properties that the examples you use in your general TDD flow wouldn’t find.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I imagine this is how a lot of QAs think. They tend to be a bit detached from the code we write and really &lt;em&gt;think&lt;/em&gt; about the domain and how things can fall apart. Property based testing allows us to capture these kind of rules as tests.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Going beyond simple types&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Property-based testing relies on generators for types to create random data for your tests. It’s simple to imagine how this works for integers but what about your own types?&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type LatLong struct{&#xA;    Lat float64&#xA;    Long float64&#xA;}&#xA;&#xA;func (l LatLong) Generate(rand *rand.Rand, size int) reflect.Value{&#xA;    randomLatLong := LatLong{&#xA;        Lat: rand.Float64(),&#xA;        Long: rand.Float64(),&#xA;    }&#xA;    return reflect.ValueOf(randomLatLong)&#xA;}&#xA;&#xA;func TestLatLongIsAlwaysTrue(t *testing.T){&#xA;    assertion := func(x LatLong) bool {&#xA;        t.Log(&amp;quot;Random LatLong:&amp;quot;, x)&#xA;        //todo: Do some interesting assertions!&#xA;        return true&#xA;    }&#xA;&#xA;    if err := quick.Check(assertion, nil); err != nil {&#xA;        t.Error(err)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;All you have to do is implement the &lt;a href=&#34;https://golang.org/pkg/testing/quick/#Generator&#34;&gt;Generator interface&lt;/a&gt; for your type. Go will provide you with a &lt;code&gt;rand&lt;/code&gt; to help you generate random data.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Conclusion&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To write effective property-based tests you have to take a step back and think deeply about the rules of your domain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Once you gain this deep understanding you can then express them very easily with property-based tests which will help you find bugs before you get to production.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The tooling in Go facilitates easily writing these specifications, even for your own types so there’s no excuse not to try it in your current project.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Notes&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/quii/quickcheck-example&#34;&gt;You can check out the code on github&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;I learned how to do quickcheck in Go by &lt;a href=&#34;https://golang.org/pkg/testing/quick&#34;&gt;RTFM&lt;/a&gt;. I suggest you do too because it offers a number of options and configurations I didn&#39;t cover here.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://skillsmatter.com/skillscasts/6432-the-lazy-programmers-guide-to-writing-1000s-of-tests-an-introduction-to-property-based-testing&#34;&gt;The talk that really got me interested in property-based testing&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 07 Mar 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Estimates</title>
      <link>https://quii.dev/Estimates</link>
      <description>&lt;p&gt;Why do developers whine about doing estimates? All the business wants is just some kind of assurance that their important project will be done by a given date. What’s the big deal?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let’s be clear here, &lt;em&gt;estimates are always wrong&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That’s not the worst of it. When you lock your development team in a room for a few hours to try and estimate 100 stories you are now suddenly back in the waterfall world. You are committing yourself to a set piece of work that cannot change.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Which is what I thought as an industry we had got past. These are inarguable facts about software development&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Priorities change&lt;/li&gt;&#xA;&lt;li&gt;Knowledge (about a system being developed) changes&lt;/li&gt;&#xA;&lt;li&gt;Teams change (they get better, usually)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Not only is it impossible to say “40 features will be delivered by April”, but you shouldn’t want to either!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In X weeks time, you will have a better understanding of what you want and the development team will be better equipped to help you make those decisions. Upfront estimations take you away from this.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The estimates I do like&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A finger in the air estimate of a bunch of high-level features can of course be given. These are ok because everyone knows that they’re vague and subject to change&lt;/li&gt;&#xA;&lt;li&gt;Relative weighting of features. This is actually the only estimate that’s important because it helps the business make a decision based on a sense of reality.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Estimation sessions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;“Estimation sessions” where a gigantic pile of stories are dropped at the feet of developers locked in a room for a few hours, points to big flaws in your process.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It doesn’t acknowledge that change happens&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Only when you &lt;em&gt;actually start doing the work&lt;/em&gt; do the real problems you’re facing become clear. There will be stuff you missed which will effect your to-the-day timescales.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;It implies you’re doing mini waterfall, not agile&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I am often astonished when I see these huge piles of cards. Where have they come from? What happened to the principles of lean-ness and doing just the work you need and then moving your priorities as and when you need them?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You have done the “analysis” stage of waterfall already it seems. You have looked into your crystal ball and worked out all the features that your customers need.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The software project fallacy&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You have a deadline and I understand this. I hope you understand that if your software is worthwhile that it will still need work on it after your deadline. If it’s not worthwhile, why are we building it?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;At the very least it will need maintenance but if your software is actually good, by setting a hard deadline you are really shooting yourself in the foot.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;People often forget that what’s really good about software is &lt;em&gt;you can change it&lt;/em&gt;. The industry has dedicated so much energy in trying to make software malleable, yet so often we are poor at selling this to the people paying our wages.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By setting hard deadlines you are creating a precedent that you know what your customers want and that their needs never change. Quite the claim.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Go back to basics&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Build, measure, learn&lt;/em&gt; over a small handful of the most important features. Discover what features are actually important and get it right. Everyone will learn about the product and you may develop something completely unexpected.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you do this in a collaborative way with the business you will get out of the mindset of software being a static thing that you make and throw away.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If the parties engage together they can make something &lt;em&gt;better&lt;/em&gt;. The software development team is not seen as a cost-centre but an asset that can actually respond to changing needs.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Fine-grained estimations disregard many of the good principles around lean, agile software development. Instead of trying to predict when a set-in-stone list of features will be done, acknowledge the unknown of business needs and if you create a truly collaborative team you can build a better product than you imagined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You cant escape deadlines. But you should be focusing your efforts on building a team that works hard at becoming efficient at writing maintainable, &lt;strong&gt;useful&lt;/strong&gt; software by working with the business/customers and &lt;strong&gt;responding to changing needs&lt;/strong&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;There is some interesting debate around this on &lt;a href=&#34;https://twitter.com/hashtag/NoEstimates?src=hash&#34;&gt;twitter&lt;/a&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Tue, 29 Dec 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Terror Handling</title>
      <link>https://quii.dev/Terror_Handling</link>
      <description>&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Happy_path&#34;&gt;The Happy path&lt;/a&gt; of writing software is usually the easiest part and coincidentally is the the thing focused on most during estimation. A lack of thought behind error handling can have big consequences on the long term health of a code base.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am going to contrast on the 3 main methods of handling errors that I have come across, &lt;em&gt;exceptions&lt;/em&gt;, &lt;em&gt;product types&lt;/em&gt; (i.e tuples) and &lt;em&gt;sum types&lt;/em&gt; (Try, Either, et al).&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The problem with exceptions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;On the face of it exceptions seem convenient but most people understand that you need to apply a lot of good practice for them not to be a pain. There is countless literature about the misuses of exceptions, from &lt;a href=&#34;http://c2.com/cgi/wiki?PokemonExceptionHandling&#34;&gt;Pokemon exception handling&lt;/a&gt; to using exceptions as control flow.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The best use-case for exceptions is when you “know” it can’t be recovered from. The problem is exceptions tend to be conflated with normal errors that you do want to recover from.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you use exceptions like this then it impacts code re-use. By throwing exceptions you are losing &lt;a href=&#34;https://en.wikipedia.org/wiki/Referential_transparency&#34;&gt;referential transparency&lt;/a&gt;, which means you cannot trust the type system; &lt;code&gt;getFoo&lt;/code&gt; might not return a &lt;code&gt;Foo&lt;/code&gt; for all inputs (it is not a &lt;a href=&#34;https://en.wikipedia.org/wiki/Partial_function#Total_function&#34;&gt;total function&lt;/a&gt;). This means that reasoning your code becomes more difficult (because you need to check the source to see the real behaviour) and it is harder to simply plug functions together.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Product types to the rescue?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;The debate around error handling is fairly prominent in the Go community, mainly because it doesn’t &lt;a href=&#34;http://blog.golang.org/defer-panic-and-recover&#34;&gt;really*&lt;/a&gt; have exceptions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The language supports tuples so the convention is to simply return the error to the caller if there is one.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot;&#xA;&#xA;func printer(f func() (string, error)){&#xA;    result, err := f()&#xA;    if err != nil {&#xA;        fmt.Println(&amp;quot;Fail!&amp;quot;, err)&#xA;    } else {&#xA;        fmt.Println(&amp;quot;Success!&amp;quot;, result)&#xA;    }&#xA;} &#xA;&#xA;func niceFunc() (string, error){&#xA;    return &amp;quot;Whoop&amp;quot;, nil&#xA;}&#xA;&#xA;func main() {&#xA;    printer(niceFunc)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;In this case &lt;code&gt;niceFunc&lt;/code&gt; is referentially transparent and the higher order function lets us know that it wants a function which &lt;em&gt;could&lt;/em&gt; return an error and will act on it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This explicitness means you don’t have to look into the implementations of functions to check for exceptions being thrown and the compiler (&lt;a href=&#34;https://github.com/kisielk/errcheck&#34;&gt;and tooling&lt;/a&gt;) will complain if you try and pretend a function could never return an error.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;There is a better way&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;In simple examples it doesn’t seem so bad, but a lot of Go code is littered with these kind of checks. The main problem is that it is very difficult to compose potentially failing functions into new functionality.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import &amp;quot;fmt&amp;quot; &#xA;&#xA;func func1() (string, error){&#xA;    return &amp;quot;Whoop&amp;quot;, nil&#xA;}&#xA;&#xA;func func2(input string) (string, error){&#xA;    return &amp;quot;&amp;quot;, fmt.Errorf(&amp;quot;Bwahahaha&amp;quot;)&#xA;}&#xA;&#xA;func func3(input string) (string, error){&#xA;    return &amp;quot;Yippee&amp;quot;, nil&#xA;}&#xA;&#xA;func main() {&#xA;    // We want to chain func1, func2, func3, bailing if we get an error&#xA;    res1, err := func1()&#xA;&#xA;    if err != nil{&#xA;        return&#xA;    }&#xA;&#xA;    res2, err := func2(res1)&#xA;&#xA;    if err != nil{&#xA;        return&#xA;    }&#xA;&#xA;    finalResult, err := func3(res2)&#xA;&#xA;    if err != nil{&#xA;        return&#xA;    }&#xA;&#xA;    fmt.Println(finalResult)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Scala (and others) lets you write &lt;a href=&#34;https://en.wikipedia.org/wiki/Tagged_unionMML242&#34;&gt;sum-types&lt;/a&gt; which allow you to encapsulate these very common computations in the type system in such a way that you can be explicit &lt;em&gt;and&lt;/em&gt; still write your code in a declarative and convenient way.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;case class DomainError(context: String, error: String)&#xA;&#xA;// this is using scalaz&#39;s either type&#xA;def func1(): DomainError \/ String = ??? // so in this case it can return either a DomainError or a String&#xA;def func2(x: String): DomainError \/ String = ???&#xA;def func3(x: String): DomainError \/ String = ???&#xA;&#xA;// see how easy it is to compose functions&#xA;def functionsComposed: \/[DomainError, String] = func1 flatMap func2 flatMap func3&#xA;&#xA;// take our newly composed function and pattern match&#xA;def process = functionsComposed match{&#xA;  case -\/(err:DomainError) =&amp;gt; // do something with error&#xA;  case \/-(result: String) =&amp;gt; // do something with result&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;As you can see, i am declaratively gluing the functions which could fail together. If they fail at any point then the result becomes a &lt;code&gt;DomainError&lt;/code&gt; and doesn’t call the following functions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s important to note that the respective functions don’t “care” about this composition, i didn’t have to do anything special other than declare that there might be an error using the type system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This approach has the referential transparency of Go whilst being more convenient and declarative&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Summary&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you raise errors to a first class citizen in your code by asking the compiler for help, you improve the re-usability and understandability of your code; not to mention it will be more robust as you won’t be having uncaught exceptions flying around.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;As your type system becomes more expressive the perceived convenience of exceptions over explicitness disappears.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Fri, 20 Nov 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The lessons I learned from SpringerLink if i was making a website from scratch again </title>
      <link>https://quii.dev/The_lessons_I_learned_from_SpringerLink_if_i_was_making_a_website_from_scratch_again_</link>
      <description>&lt;p&gt;&lt;a href=&#34;http://link.springer.com&#34;&gt;SpringerLink&lt;/a&gt; is the biggest project I’ve been involved with. It was completely different to every other project in terms of scale and complexity. It was my first real introduction to agile software development and writing software that was actually &lt;em&gt;used by lots of people&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I learnt a lot of random lessons from working on a system developed by hundreds of people and I thought it was an interesting thought experiment to think about what I would do if I were to start again&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So in no particular order…&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Agile&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We were at our fastest when we were developing simple, well understood features that could be done in a week. Even if it’s hard it’s worth the effort to try and trim the fat off a feature. Usually features that take &amp;gt; 2 weeks don’t go well.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Done is when it’s live&lt;/strong&gt;, if you have a big pile of stuff that’s no longer worked on but is on a branch or not released than that is a huge problem that gets worse with every commit. The reason is to do with feedback loops. If you find a problem in a new feature it becomes more and more difficult for a team to fix it the longer it’s left alone.&lt;/li&gt;&#xA;&lt;li&gt;We like to see stories going from left to right (i.e, analysis, in dev, qa, live, etc) but it is not the end of the world if stories move backwards. In fact, that usually means you’ve learnt something. At times I have seen situations where stories have been “not ready” for a very long time. &lt;strong&gt;Some&lt;/strong&gt; upfront analysis is important to cut waste but there comes a point where you just need to try it and then you’ll learn rather than speculate.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Continuous delivery&lt;/strong&gt; (i.e green build = live) is a &lt;em&gt;really&lt;/em&gt; nice thing. It’s a shame that releases are still a “thing” for us. The moment software starts going to live on successful builds is the moment people take more ownership of code and you get feedback.&lt;/li&gt;&#xA;&lt;li&gt;Remember that agile development is meant to be &lt;strong&gt;iterative&lt;/strong&gt;. Get basic skeletal features to live and then improve them. Don’t turn it into a waterfall project delivering in increments.&lt;/li&gt;&#xA;&lt;li&gt;UX research should not be a recipe for paralysis. If you don’t know, take a punt and then test. If you are in a state where you think changing UX would be too hard so you need to do a lot of upfront research then maybe something else is wrong. One of the reasons why Agile came about is because upfront analysis is almost never as good as build, measure, learn. This &lt;em&gt;does&lt;/em&gt; apply to UX.&lt;/li&gt;&#xA;&lt;li&gt;Tech tasks are important, but can expand to fill the volume you give them. Make the developers feel exicted and interested in the project as a whole so they can strike the right balance in their own minds.&lt;/li&gt;&#xA;&lt;li&gt;“YAGNI” is a useful stick but don’t use it too often. My rule of thumb in general is do the minimum to get the minimum functionality and at that point you can make a more informed choice as to how you gild the lily.&lt;/li&gt;&#xA;&lt;li&gt;Actually measure build time and don’t let it get awful. Report it, every week.&lt;/li&gt;&#xA;&lt;li&gt;Refactor. If the business doesn’t let you, just fucking quit. Also refactoring shouldn’t be a &lt;em&gt;thing&lt;/em&gt;. What I mean by that is developers should be empowered to write good software and not have to report every little detail.&lt;/li&gt;&#xA;&lt;li&gt;Don’t have stats on a new feature? Why not? &lt;strong&gt;How do you know a feature is successful?&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;/Unused%20features%20are%20technical%20debt&#34;&gt;Why aren’t you deleting features?&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;NFRs (Non-functional requirements) are important&lt;/strong&gt; and should be considered for every story, it doesn’t need to take up a lot of time. Too often we have gone live with something without logging and metrics to help support the change.&lt;/li&gt;&#xA;&lt;li&gt;Retrospectives are really useful but can sometimes go down focusing on a small issue which ends up being blown out of proportion. Needs strong facilitation with someone who has good context on the group. &lt;strong&gt;Everything that goes awry does not need a process change&lt;/strong&gt;. It’s like dropping a footballer every time he misses a pass.&lt;/li&gt;&#xA;&lt;li&gt;On the other hand, especially in a stable team retrospectives can become too “safe”, not tackling real incumbent issues that maybe the team takes for granted. You should always be asking yourself &lt;em&gt;how can we go faster/better?&lt;/em&gt;. A good facilitator can really help this, usually by structuring the retro in a different way to try and make a team think about things differently. Have a look through Game Storming for ideas.&lt;/li&gt;&#xA;&lt;li&gt;Meetings are important and can be very productive but they need good facilitation and most importantly a focused goal. I have been in too many meetings that have drifted and dived into irrelevant tangents.&lt;/li&gt;&#xA;&lt;li&gt;Everyone wants a culture of developers “just fucking do it”, but that requires trust in devs and less micromanagement of their time. This contradicts “process” sometimes and is a hard balance to get right.&lt;/li&gt;&#xA;&lt;li&gt;If your PM insists on story points, dont make it an issue - but don’t report them upwards as it just causes games which is an inefficiency.&lt;/li&gt;&#xA;&lt;li&gt;That being said, everyone ultimately knows &lt;strong&gt;estimates are bollocks&lt;/strong&gt;. Just refine your process and measure how long real features take to deliver and that gives you your cadence for future planning.&lt;/li&gt;&#xA;&lt;li&gt;Why are you estimating work that won’t happen for &amp;gt; 6 months? It’s a waste of time for everyone.&lt;/li&gt;&#xA;&lt;li&gt;Why are you talking about work at any level of detail that won’t happen for 6 months?&lt;/li&gt;&#xA;&lt;li&gt;Document decisions somehow. 2 years down the line you will struggle to justify your decisions but you probably were doing the most rational thing for the given situation/knowledge.&lt;/li&gt;&#xA;&lt;li&gt;Stakeholders need to feel involved, informed and consulted. But it is the product team’s job to make the detailed decisions.&lt;/li&gt;&#xA;&lt;li&gt;Process change is sometimes important, but you need to stick with it for longer than a month to understand if it works. Constant process change just pisses everyone off and slows everything down.&lt;/li&gt;&#xA;&lt;li&gt;“Process” is often synonymous with micromanagement (in my brief experience) which most developers hate. They almost always boil down to trying to paper over cracks in communication. With an &lt;strong&gt;engaged&lt;/strong&gt; and enthusiastic team who understand the value of all roles and the vision of the product you will get all this for free.&lt;/li&gt;&#xA;&lt;li&gt;It’s so much harder to refactor code 3 months later; even if the code around it doesn’t change because people and context change. Don’t pay lip service to this, this has cost us lots of time and effort. Just give space between stories to tidy up properly and it will save lots of money&lt;/li&gt;&#xA;&lt;li&gt;Related: “big refactors” are very dangerous things, especially when new people come in and want to change everything to suit the paradigms they are used to. &lt;strong&gt;How do you measure the success of this? That’s your warning, for literally everything in software&lt;/strong&gt;. Pick your measurements carefully too. If you speed up the build but make the code hard to follow, that is not a success.&lt;/li&gt;&#xA;&lt;li&gt;Measuring success is hard but it doesn’t have to necessarily be a number so long as you’re honest with yourselves and have a good idea of what success is. We have done work which we &lt;em&gt;know&lt;/em&gt; has helped in the long run but you can’t possibly put a number to it. The trouble happens when there isn’t a consensus as to what success looks like, which hurts motivation and is wasteful.&lt;/li&gt;&#xA;&lt;li&gt;Even though you’re developing software incrementally there should be an overall &lt;em&gt;plan&lt;/em&gt; in terms of technical direction. In addition you &lt;em&gt;must&lt;/em&gt; include everyone or people will absolutely feel left out and will resent that.&lt;/li&gt;&#xA;&lt;li&gt;Performance can become a second class citizen which gets delayed until the end of a milestone. Try and incorporate performance metrics sooner rather than later.&lt;/li&gt;&#xA;&lt;li&gt;As a developer working closely with your BAs and QAs is invaluable. Don’t become one of those devs that just mindlessly picks up stories without talking to people. Remember it is everyone’s responsibility to deliver features end to end. &lt;em&gt;You&lt;/em&gt; can help clarify the goal of a story with the BA and QA. &lt;em&gt;You&lt;/em&gt; can help make the story easy to test. &lt;em&gt;You&lt;/em&gt; can help the BA use technology to measure the value of the story. It shouldn’t be a chore, you’re wrong to think it is and you’re wrong to think it takes too much time.&lt;/li&gt;&#xA;&lt;li&gt;Put less diplomatically: - ALL FUCKING TALK TO EACH OTHER ABOUT THE WORK. SERIOUSLY. WHY WOULD A STORY BE PLAYED WHEN NO ONE HAS SAT TOGETHER AND TALKED ABOUT IT AS A GROUP. WHYYYY?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;People&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The right amount and kind of pressure is good. Too much is demoralising and destructive. None at all is also demoralising, and will lead to drift. Set near-term customer-facing objectives that are just challenging enough.&lt;/li&gt;&#xA;&lt;li&gt;Motivation is hard but visibility of value being delivered really helps.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Don’t be a bastard&lt;/strong&gt;. People (including yourself) take shortcuts for legit reasons a lot of the time. Most especially everyone (&lt;em&gt;you&lt;/em&gt;) makes mistakes or is less experienced with what’s going on. Everything is fixable, eventually. Only be a bastard to people who won’t listen.&lt;/li&gt;&#xA;&lt;li&gt;A noisy, jolly standup is not necessarily indicative of a productive team. Neither is a quiet one. Don’t judge a team on such superficial things. What does their product owner think?&lt;/li&gt;&#xA;&lt;li&gt;In the same way, one team works with paradigm/language/framework X. You use Y. Why do you care? Are you all delivering good software? That’s all that matters.&lt;/li&gt;&#xA;&lt;li&gt;You’re probably doing better than you think as it’s easy to focus on the negatives. Make sure you take the time to &lt;strong&gt;celebrate the good stuff&lt;/strong&gt; the team has done, especially in an organisation with lots of teams.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Technical&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Read &lt;a href=&#34;http://12factor.net/&#34;&gt;The 12 factor app&lt;/a&gt;. It helps you write software that works beyond your desktop.&lt;/li&gt;&#xA;&lt;li&gt;Be really strict with statefulness. Things like feature toggles, properties and stuff should either require a server restart or be managed on a request based level. This makes testing simpler and the code much easier to write. If you see tests which are setting and unsetting things, then your server has state. Stop it.&lt;/li&gt;&#xA;&lt;li&gt;Just use environment variables for config. You don’t need any more complexity than that most of the time. Managing configuration outside the app then becomes language and platform agnostic. Your software is then more likely to be compatible with most PaaS solutions.&lt;/li&gt;&#xA;&lt;li&gt;No logic in templates, seriously. This has caused us no end of pain.&lt;/li&gt;&#xA;&lt;li&gt;Don’t use some complicated build tool to do basic things bash can do. Such as… making a zip file.&lt;/li&gt;&#xA;&lt;li&gt;If your template language doesn’t look like HTML, don’t use it. It might seem fancy and, darn closing those tags is annoying but having to mentally parse template files years down the line is really painful.&lt;/li&gt;&#xA;&lt;li&gt;Controllers should all look the same. They have some dependencies injected in. Each endpoint parses a request, calls a service and then calls a template with a view model. Anything else is bullshit and is a barrier to understand how particular requests in your system are processed.&lt;/li&gt;&#xA;&lt;li&gt;Beware of &lt;em&gt;The Onion&lt;/em&gt;. Code should read in a declarative way so you understand on a broad level &lt;em&gt;what&lt;/em&gt; is happening. This doesn’t mean don’t do encapsulation. Encapsulation means hide &lt;em&gt;how&lt;/em&gt; something happens. If it’s hard to understand &lt;em&gt;what&lt;/em&gt; is going on then you just need to fix it. &lt;em&gt;The Onion&lt;/em&gt; is when you have to dart between a lot of files just to understand &lt;em&gt;what&lt;/em&gt; is happening in a system and eventually you have a stack overflow in your brain where you cant handle the call chain anymore.&lt;/li&gt;&#xA;&lt;li&gt;Logging/events. Don’t have static imports, services should delegate to a “listener”. Logging/metrics is important and should be treated as something that needs to be testing. It seems odd at first but really it isn’t much effort at all and then you can be confident of finding information at 3am when everything blows up.&lt;/li&gt;&#xA;&lt;li&gt;Trying to encapsulate loads of behaviours in libraries is almost always a bad idea. Saying “doing HTTP and getting circuit breaking, metrics, exceptions yada yada should be standard” is nonsense. Even if it is standard, some day it won’t fit into what we need to do. Composition FTW.&lt;/li&gt;&#xA;&lt;li&gt;Try not to couple different concerns into one piece of data. In our case having “has Access” coupled with the content meant we cannot cache it.&lt;/li&gt;&#xA;&lt;li&gt;Follow general good OSS principles. It should be clear how to build the software from a README.&lt;/li&gt;&#xA;&lt;li&gt;If you use a whacky language like Scala where it’s not very opinionated then a CONTRIBUTING.txt is a useful way to get to a consensus as to how your code should look.&lt;/li&gt;&#xA;&lt;li&gt;Really think about how you work and what inefficiencies there are and build tooling to overcome it. It was silly how long it took us to have a tool to copy a document from live on to the local box.&lt;/li&gt;&#xA;&lt;li&gt;If you’re using a statically typed language refuse to use “escape-hatches”. In Scala doing things like “asInstanceOf” is a real code smell and is asking for a runtime error to occur.&lt;/li&gt;&#xA;&lt;li&gt;If you have a language with a half-decent type system, use it! Code re-use and maintainability can be significantly improved by reflecting everything in the type system. The moment you dont have this (exceptions,nulls,etc) is the moment you have to employ &amp;quot;defensive&amp;quot; (paranoid) programming.&lt;/li&gt;&#xA;&lt;li&gt;Feature toggles are really useful for degrading the system gracefully in live and also can help testing. In the past we have suffered from having to set specific access rights to test features that have little to do with access rights. If only we had an “all access” feature those tests would be quicker to run and simpler to write.&lt;/li&gt;&#xA;&lt;li&gt;Making feature toggles a request level concern means you can do things like set a cookie to test a feature in live.&lt;/li&gt;&#xA;&lt;li&gt;As a functional programmer I really love purity and you can still apply these principles in imperative languages but also in services (i.e APIs). Idempotency is a really powerful thing which makes error handling and general understanding much better. You can always be confident of doing a PUT request more than once wont have some crazy side-effect. Strive to make the endpoints of your APIs as idempotent as possible.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Tests&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Make sure everyone is onboard with what kinds of tests you do and what they’re responsible for. For instance:&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Unit tests should be really fast and should not be reliant on anything external (file system, network, etc). Start your project by running these in parallel and then that puts a good restriction as to what you can do. Trying to make them parallelisable a year later is often already a lost cause.&lt;/li&gt;&#xA;&lt;li&gt;Integration tests should be testing how your system communicates with another &lt;em&gt;and that’s all&lt;/em&gt;. Resist the temptation to start re-testing the downstream service, which complicates your mocks. They should &lt;em&gt;only&lt;/em&gt; test “does the system do the correct request and can it parse the responses it might get. Separate out everything else.&lt;/li&gt;&#xA;&lt;li&gt;Functional tests are expensive in terms of time and maintenance and therefore should be kept to a minimum. Try and cover key scenarios and the rest should be tested lower down in unit and integration tests.  Do they need to test specific rendering of things? Should your functional test fail if the markup changes from a &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt; to an &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt;?&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/li&gt;&#xA;&lt;li&gt;Functional tests don’t &lt;em&gt;have&lt;/em&gt; to be done through a browser. Why not make your page have a JSON equivalent view that is easier to test. That will also prove you have decoupled your data from your view (i.e a View Model).&lt;/li&gt;&#xA;&lt;li&gt;Just use fake servers rather than a generic stub framework. The lack of flexibility with fake servers is usually a &lt;em&gt;good thing&lt;/em&gt;.  You should not have logic in your fakes.&lt;/li&gt;&#xA;&lt;li&gt;Run your consumer driven contracts against both your fakes and the real downstream service. That way you can be sure your integration tests reflect reality. Perhaps you should use something awesome like &lt;a href=&#34;https://github.com/quii/mockingjay-server&#34;&gt;mocking-jay&lt;/a&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;Visualise your test pyramid and try and make it look like the one described by &lt;a href=&#34;http://martinfowler.com/bliki/TestPyramid.html&#34;&gt;Martin Fowler&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&#xA;&#xA;&lt;li&gt;&lt;p&gt;If lots of tests unrelated to your change fail then you have some nasty coupling going on there.&lt;/p&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Wed, 01 Jul 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Books I&#39;ve read recently</title>
      <link>https://quii.dev/Books_I&#39;ve_read_recently</link>
      <description>&lt;p&gt;I can’t sell these books well enough, which is why I’m not an author or a salesman. I did really enjoy them, you might too.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Nature of Software Development&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you’ve practiced agile software development for a while this will feel like an echo chamber, there’s nothing really new here. But it’s a reassuring echo chamber when things aren’t quite going as well as you’d like.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It reminds you how simple it can all be and that is reflected in how easy it is to read. It can easily be read over a weekend.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Lean Startup&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A bit of a classic, the book directs you to measure the success of every feature you make and see if it’s valuable, to hopefully point you toward a successful product.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It’s very tightly bound with agile software, &lt;em&gt;build measure learn&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It can sometimes be quite hard to put into practice but every time you don’t follow it’s principles you know you’re making excuses.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;“Make useful products” - harder than you think.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Outliers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This book discusses how people become successful or not. It tries to debunk the romanticism that is put behind entrepreneurs and instead analyses the situations that surround them and how they really benefit them, or not.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That’s not to say talent doesn’t play a part, just that it’s only part of the equation. It’s a fascinating book with some great stories of success but really makes you think about how society is so potentially wasteful of talent.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Power of Habit&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Yet more pop psychology, but a really fascinating read on how prominent habit is not only your own life but in organisations. It’s a fun look at human nature and how it is possible to change those bad habits, and where people/companies get it wrong.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Reality is broken&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This is a lovely book on gamification, talking about how people get into the zone and become productive. It’s easy to think about this as a guide book into making cheesy apps to try and make a quick buck but it has also made me think about how my own productivity is effected by things such as distractions or the way the work is laid out.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Thinking fast and slow&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;This books teaches you to think about the way you think. This is quite important because &lt;em&gt;you are biased&lt;/em&gt;. It essentially weighs up your fast brain (instinct) and slow brain (deeper thinking) and when you should trust them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It aims to make you better at decision making, which everyone should be interested in.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;In progress&lt;/h2&gt;&#xA;&#xA;&lt;h3&gt;Cakes, custard and Category Theory&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;I wish Eugenia Cheng had been my maths teacher. In light of reading Outliers I wish she was everyone’s maths teacher.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;She really “sells” mathematics beautifully in a way that just makes you want to do it all over again.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I think my favourite point she has made so far is how people often accuse abstraction as being too divorced from reality to be useful. When actually, abstraction is zooming in on the &lt;em&gt;essence&lt;/em&gt; of ideas. Maths has always had a close relationship with programming but I don’t think I’ve appreciated it as much as I have now that I’ve read only 25% of this book.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;The Glimpse of Truth: The 100 finest short stories ever written&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;In my attempt at being slightly more cultured I thought I’d read something that isn’t:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Tech&lt;/li&gt;&#xA;&lt;li&gt;Fantasy&lt;/li&gt;&#xA;&lt;li&gt;Pop psychology&lt;/li&gt;&#xA;&lt;li&gt;Distopia&lt;/li&gt;&#xA;&lt;li&gt;Steinbeck&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;The price of inequality&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Being a bleeding heart liberal I get wound up easily over my perceived injustices in the world. I truly believe that if we could open up opportunities for everyone (hello again, Outliers) we can all benefit. This book, by Nobel Prize winning economist Joseph Stiglitz, describes how we’re totally fucking it all up.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;And books on my list…&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Lean Enterprise&lt;/li&gt;&#xA;&lt;li&gt;The little ML-er&lt;/li&gt;&#xA;&lt;li&gt;Learn You a Haskell For Great Good (attempt #3)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 22 Jun 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Improving the quality and performance of your code, guided by the tooling in Go</title>
      <link>https://quii.dev/Improving_the_quality_and_performance_of_your_code,_guided_by_the_tooling_in_Go</link>
      <description>&lt;p&gt;What’s rad about writing Go is how the tooling is really well catered to every day software development concerns.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I recently did a lunch and learn at Springer on why I think Go is great and did a case-study showing how Go makes it easy to create consistent looking, performant and reliable code.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Goal&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We are going to write a function which calls two APIs, one is the “Hello” service and the other is a “World” service. Our code will stitch the results together to return the string “Hello, World”.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Iteration 1&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;To start off we’ll just get the signature of our function together so we can write a failing test against it.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Stitcher(hello_url string, worldURL string) string {&#xA;    return &amp;quot;&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Before we get too excited though, let’s run &lt;a href=&#34;https://github.com/golang/lint&#34;&gt;golint&lt;/a&gt;. Go Lint is a tool which points out style inconsistencies in your code. One of the key goals for the language is that all the code should feel recognisable and consistent, we can see that I have already made some mistakes.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;stitcher.go:7:1: exported function Stitcher should have &#xA;comment or be unexported&#xA;stitcher.go:7:15: don’t use underscores in Go names; &#xA;func parameter hello_url should be helloURL&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Whether you think comments are good or not, what’s nice about this message is that it makes you think about the public surface of your library. Does every function need to be public? Probably not. However if you do cave in to the linter’s demands, the GoDoc tool will make some &lt;a href=&#34;https://godoc.org/github.com/quii/go-perf-test-example&#34;&gt;lovely documentation&lt;/a&gt; for your code; so it’s worth the effort.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Stitcher calls the Hello and World APIs to create a very useful string&#xA;func Stitcher(helloURL string, worldURL string) string {&#xA;    return &amp;quot;&amp;quot;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Admittedly a small improvement in this context, but in larger code bases consistent naming and well documented public methods will help you out. The linter tool, like all Go tools are very fast so there’s little reason not to add it to your build scripts.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Now that our stub code is linted we can write a test.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;    &amp;quot;net/http/httptest&amp;quot;&#xA;    &amp;quot;testing&amp;quot;&#xA;)&#xA;&#xA;func Test_it_calls_the_services_and_concatenates_the_results(t *testing.T) {&#xA;&#xA;    helloAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        fmt.Fprint(w, &amp;quot;Hello&amp;quot;)&#xA;    }))&#xA;&#xA;    worldAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        fmt.Fprint(w, &amp;quot;world&amp;quot;)&#xA;    }))&#xA;&#xA;    result := Stitcher(helloAPI.URL, worldAPI.URL)&#xA;    expected := &amp;quot;Hello, world&amp;quot;&#xA;&#xA;    if result != expected {&#xA;        t.Errorf(&amp;quot;Stitcher failed, expected [%s], got [%s]&amp;quot;, expected, result)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Calling APIs and creating new functionality is a very common task for many developers and Go makes testing these operations a breeze all within the standard library. This test fails so now we can fill out our function with some real code that we can be reasonably confident will work and is safe to refactor.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;package main&#xA;&#xA;import (&#xA;    &amp;quot;fmt&amp;quot;&#xA;    &amp;quot;io/ioutil&amp;quot;&#xA;    &amp;quot;net/http&amp;quot;&#xA;)&#xA;&#xA;// Stitcher calls the Hello and World APIs to create a very useful string&#xA;func Stitcher(helloURL string, worldURL string) string {&#xA;&#xA;    helloResponse, _ := http.Get(helloURL)&#xA;    defer helloResponse.Body.Close()&#xA;    helloContent, _ := ioutil.ReadAll(helloResponse.Body)&#xA;&#xA;    worldResponse, _ := http.Get(worldURL)&#xA;    defer worldResponse.Body.Close()&#xA;    worldContent, _ := ioutil.ReadAll(worldResponse.Body)&#xA;&#xA;    return string(helloContent) + &amp;quot;, &amp;quot; + string(worldContent)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We know we haven’t finished yet as there is some naivety to the code in a number of places, most especially error handling, but we will get on to that later. For now we can celebrate the awesomeness of our first pass.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Iteration 2 - Performance&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The cowboys we outsourced the two APIs to have said that the APIs cannot return responses quicker than half a second. As we’re calling both APIs we can assume our awesome function will take at least a second to complete.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Intuitively we know that we could do the HTTP calls concurrently  which might halve that time.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;We shouldn’t just dive in straight away and use Go’s concurrency tools because like all things we need to validate our assumptions otherwise we could be wasting our time. We must be able to prove the code we write adds value in a repeatable way.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Let’s use Go’s benchmarking tools to simulate this and then fix the problem&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Benchmark_the_stitcher(b *testing.B) {&#xA;    slowHelloAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        time.Sleep(500 * time.Millisecond)&#xA;        fmt.Fprint(w, &amp;quot;Hello&amp;quot;)&#xA;    }))&#xA;&#xA;    slowWorldAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        time.Sleep(500 * time.Millisecond)&#xA;        fmt.Fprint(w, &amp;quot;world&amp;quot;)&#xA;    }))&#xA;&#xA;    b.ResetTimer()&#xA;&#xA;    for i := 0; i &amp;lt; b.N; i++ {&#xA;        Stitcher(slowHelloAPI.URL, slowWorldAPI.URL)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The benchmark tool will run the loop N times until it thinks it has a consistent benchmark time. Running the tool confirmed our assumption, the function takes ~1 second.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Stitcher calls the Hello and World APIs to create a very useful string&#xA;func Stitcher(helloURL string, worldURL string) string {&#xA;&#xA;    helloChannel := make(chan []byte, 1)&#xA;    worldChannel := make(chan []byte, 1)&#xA;&#xA;    go func() {&#xA;        helloResponse, _ := http.Get(helloURL)&#xA;        defer helloResponse.Body.Close()&#xA;        helloContent, _ := ioutil.ReadAll(helloResponse.Body)&#xA;        helloChannel &amp;lt;- helloContent&#xA;    }()&#xA;&#xA;    go func() {&#xA;        worldResponse, _ := http.Get(worldURL)&#xA;        defer worldResponse.Body.Close()&#xA;        worldContent, _ := ioutil.ReadAll(worldResponse.Body)&#xA;        worldChannel &amp;lt;- worldContent&#xA;    }()&#xA;&#xA;    return string(&amp;lt;-helloChannel) + &amp;quot;, &amp;quot; + string(&amp;lt;-worldChannel)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This code has successfully halved the execution time and I have the code to prove that’s the case &lt;em&gt;and&lt;/em&gt; that it still works as intended from the test we had earlier.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;That being said, the code is starting to feel a little unwieldy, there is a lot of repetition so lets use the safety net of our tests to refactor the code a bit before moving on.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;const wordSeparator = &amp;quot;, &amp;quot;&#xA;&#xA;// Stitcher calls the Hello and World APIs to create a very useful string&#xA;func Stitcher(helloURL string, worldURL string) string {&#xA;&#xA;    helloChannel := make(chan []byte, 1)&#xA;    worldChannel := make(chan []byte, 1)&#xA;&#xA;    go getStringFromAPI(helloChannel, helloURL)&#xA;    go getStringFromAPI(worldChannel, worldURL)&#xA;&#xA;    return string(&amp;lt;-helloChannel) + wordSeparator + string(&amp;lt;-worldChannel)&#xA;}&#xA;&#xA;func getStringFromAPI(ch chan&amp;lt;- []byte, url string) {&#xA;    response, _ := http.Get(url)&#xA;    defer response.Body.Close()&#xA;    content, _ := ioutil.ReadAll(response.Body)&#xA;    ch &amp;lt;- content&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3&gt;Iteration 3 - Error handling&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Now that we have a performant happy path, we should tackle the fact that HTTP calls can and will fail; so let’s write a new test to simulate this scenario and that can help us make the code more robust.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The product owners are a fairly vindictive bunch and have told us that if either API fails we are to default to a string which says “ALL OTHER SOFTWARE TEAMS ARE USELESS, OUTSOURCING IS A SHAM”&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here is our test simulating the hello API returning a 500 which results in our code panicking.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;func Test_it_handles_non_ok_from_hello_api(t *testing.T) {&#xA;&#xA;    helloAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        http.Error(w, &amp;quot;oops&amp;quot;, http.StatusInternalServerError)&#xA;    }))&#xA;&#xA;    worldAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&#xA;        fmt.Fprint(w, &amp;quot;world&amp;quot;)&#xA;    }))&#xA;&#xA;    result := Stitcher(helloAPI.URL, worldAPI.URL)&#xA;&#xA;    if result != errorMsg {&#xA;        t.Errorf(&amp;quot;Stitcher didnt fail properly, expected [%s], got [%s]&amp;quot;, errorMsg, result)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;We have a test which proves this problem so we can fix the code and be confident that this particular bug will not come up when we go to production.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;const wordSeparator = &amp;quot;, &amp;quot;&#xA;const errorMsg = &amp;quot;ALL OTHER SOFTWARE TEAMS ARE USELESS, OUTSOURCING IS A SHAM&amp;quot;&#xA;&#xA;type apiResult struct {&#xA;    content string&#xA;    err     error&#xA;}&#xA;&#xA;// Stitcher calls the Hello and World APIs to create a very useful string&#xA;func Stitcher(helloURL string, worldURL string) string {&#xA;&#xA;    helloChannel := make(chan *apiResult, 1)&#xA;    worldChannel := make(chan *apiResult, 1)&#xA;&#xA;    go getStringFromAPI(helloChannel, helloURL)&#xA;    go getStringFromAPI(worldChannel, worldURL)&#xA;&#xA;    helloResult := &amp;lt;-helloChannel&#xA;    worldResult := &amp;lt;-worldChannel&#xA;&#xA;    if helloResult.err != nil || worldResult.err != nil {&#xA;        return errorMsg&#xA;    }&#xA;&#xA;    return helloResult.content + wordSeparator + worldResult.content&#xA;}&#xA;&#xA;func getStringFromAPI(ch chan&amp;lt;- *apiResult, url string) {&#xA;    response, err := http.Get(url)&#xA;&#xA;    if err != nil {&#xA;        ch &amp;lt;- &amp;amp;apiResult{&amp;quot;&amp;quot;, err}&#xA;    } else {&#xA;        defer response.Body.Close()&#xA;        content, err := ioutil.ReadAll(response.Body)&#xA;&#xA;        if err != nil {&#xA;            ch &amp;lt;- &amp;amp;apiResult{&amp;quot;&amp;quot;, err}&#xA;        } else if response.StatusCode != http.StatusOK {&#xA;            ch &amp;lt;- &amp;amp;apiResult{&amp;quot;&amp;quot;, errors.New(&amp;quot;Non 200 response from API&amp;quot;)}&#xA;        } else {&#xA;            ch &amp;lt;- &amp;amp;apiResult{string(content), nil}&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This code makes our new test pass, hooray! Some Go experts might have some better ways to write this and that&#39;s fine because we now have a suite of tests to make sure no matter how much someone tinkers with the implementation they can be confident they have not broken existing functionality.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Summary&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Even though this is a contrived example I hope this demonstrates how Go’s ecosystem and tooling can really help to create robust, well tested and readable software.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Go makes it really easy to write maintainable open source software, if you are mad enough to want to use something that blindly concatenates two successful HTTP calls, all you need to do is&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;go get github.com/quii/go-perf-test-example&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;and then just check the almost &lt;a href=&#34;https://godoc.org/github.com/quii/go-perf-test-example&#34;&gt;entirely auto-generated go doc&lt;/a&gt; to see how to use it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The final codes are available here: &lt;a href=&#34;https://github.com/quii/go-perf-test-example&#34;&gt;https://github.com/quii/go-perf-test-example&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have any comments on feedback, please do &lt;a href=&#34;http://twitter.com/quii&#34;&gt;get in touch with me&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;I originally posted this at &lt;a href=&#34;http://spiking-the-solution.tumblr.com/post/115468047064/improving-the-quality-and-performance-of-your&#34;&gt;spiking the solution&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 04 Apr 2015 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>What is a typeclass and why should you care</title>
      <link>https://quii.dev/What_is_a_typeclass_and_why_should_you_care</link>
      <description>&lt;p&gt;Type systems are great because they protect you from lots of errors at compile time. However, sometimes it feels like it gets in your way and can make your code feel less flexible when you are trying to extend certain types that you may or may not have defined.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In dynamically typed languages this is less of a problem because of duck-typing. However, you get no safety here; if you pass in something that doesn’t quack you will get a runtime error.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Duck typing doesn&#39;t fix everything though. A human class might be able to quack with a &amp;quot;say&amp;quot; function; you would need to give your program some help in these instances&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you wish to write a generic function that operates on a variety of types, you may be tempted into writing an interface and ensuring all the types you care about implement them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But this requires changing potentially lots of code and adding in a commonality that only you care about to solve a particular problem. Ask yourself, is this polymorphism truly useful for other people? Or are you polluting the namespace for your convenience (hint: the latter).&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The &lt;a href=&#34;http://en.wikipedia.org/wiki/Design_Patterns&#34;&gt;GoF&lt;/a&gt; have a solution to this too, the &lt;a href=&#34;http://en.wikipedia.org/wiki/Adapter_pattern&#34;&gt;adapter pattern&lt;/a&gt;. But every time someone wants to use your library they will have to take their type and wrap them up in an adapter. This feels clunky to me; and of course there is a better way.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Type classes to the rescue!&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A type class &lt;em&gt;T&lt;/em&gt; is an interface that defines a set of behaviours that a type &lt;em&gt;Foo&lt;/em&gt; must implement in order to be of type &lt;em&gt;T&lt;/em&gt;. Great, so what?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you wish to have a polymorphic function, you can require evidence of a type class for the type which is being passed in. This can be &lt;em&gt;any&lt;/em&gt; type because a developer can provide this evidence wherever they like; i.e not within the type itself.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is a great strength of type classes because it addresses the flaws of the other approaches:&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Any arbitrary type can use your library if they implement your typeclass; no need for access to the source code.&lt;/li&gt;&#xA;&lt;li&gt;No need to pollute namespace of types only for your needs. Clear separation of concerns and still polymorphic&lt;/li&gt;&#xA;&lt;li&gt;No wrappers needed. Scala&#39;s implicit means you can pass in your type to the library function without noisy adapters; makes your code easier to follow.&lt;/li&gt;&#xA;&lt;li&gt;Type safety.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt; Example&lt;/h3&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// Pretend this is your awesome library code that you want others to use freely&#xA;object MyAmazingSerialisationLib{&#xA;&#xA;  trait Serialiser[A]{&#xA;    def toJson(x: A): String&#xA;  }&#xA;&#xA;  def writeJsonToDisk[A](item: A)(implicit serialiser: Serialiser[A]){&#xA;    def writeToDisk(x: String) {println(s&amp;quot;I saved [$x] to disk, honest!&amp;quot;)}&#xA;    writeToDisk(serialiser.toJson(item))&#xA;  }&#xA;}&#xA;&#xA;object TypeClasses extends App {&#xA;&#xA;  import MyAmazingSerialisationLib._&#xA;&#xA;  case class Dog(name: String)&#xA;&#xA;  case class ComputerMachine(id: Int, complexity: Int)&#xA;&#xA;  implicit val dogSerialiser = new Serialiser[Dog] {&#xA;    def toJson(dog: Dog) = s&amp;quot;&amp;quot;&amp;quot;{&amp;quot;name&amp;quot;:&amp;quot;${dog.name}&amp;quot;}&amp;quot;&amp;quot;&amp;quot;&#xA;  }&#xA;&#xA;  // compiles because we have evidence of serialiser&#xA;  writeJsonToDisk(Dog(&amp;quot;Spot&amp;quot;))  &#xA;&#xA;  // doesn&#39;t compile because we dont have a serialiser in scope&#xA;  writeJsonToDisk(ComputerMachine(2, 20)) &#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Scala provides sugar to make it so your function&#39;s &lt;em&gt;type&lt;/em&gt; can reflect it&#39;s needs, rather than having it as a parameter. You can replace the function from above with the code below and it will continue to work.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;// [A: Serialiser] means the compiler expects an implicit Serialiser &#xA;// needs to be available for A&#xA;def writeJsonToDisk[A: Serialiser](item: A){&#xA;  def writeToDisk(x:String){println(s&amp;quot;I saved [$x] to disk, honest!&amp;quot;)}&#xA;&#xA;  // Access the parameter with implicity&#xA;  writeToDisk(implicitly[Serialiser[A]].toJson(item))&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This syntax can provide more flexibility in terms of not having to pass implicit parameters to other sub-functions; your function just requires &amp;quot;evidence&amp;quot; of a type-class.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However, people in your team may be more familiar with an implicit parameter so be sure to explain things whenever you introduce exotic symbols into your code-base.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Conclusion&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Type classes are easy to use and an interesting functional design pattern for your tool-belt.&lt;/li&gt;&#xA;&lt;li&gt;Enables “ad-hoc” polymorphism but with type safety.&lt;/li&gt;&#xA;&lt;li&gt;Allows users of your useful functions to use them with any type without having to change their own types.&lt;/li&gt;&#xA;&lt;li&gt;Easier to separate concerns without making lots of types/adapters.&lt;/li&gt;&#xA;&lt;li&gt;Essential for making your library code re-usable and extensible; a very common approach in the standard Scala libraries and popular open source projects.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Other links&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/tpolecat/tut/blob/master/out/Typeclass.md&#34;&gt;https://github.com/tpolecat/tut/blob/master/out/Typeclass.md&lt;/a&gt; - Great code example; plus you will accidentally find out what a Monoid is.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html&#34;&gt;http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html&lt;/a&gt; - Probably a better explanation&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;I originally posted this at &lt;a href=&#34;http://spiking-the-solution.tumblr.com/post/82675003050/what-is-a-type-class-and-why-should-you-care&#34;&gt;spiking the solution&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Tue, 01 Apr 2014 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Unused features are technical debt</title>
      <link>https://quii.dev/Unused_features_are_technical_debt</link>
      <description>&lt;p&gt;Technical debt is often described on a low level, where developers will take some kind of shortcut in order to deliver a feature quicker; at a cost to future development which must be &amp;quot;paid&amp;quot; sometime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However technical debt can manifest itself in many different ways and one way it has reared it&#39;s head on a project I am working on is by unused features.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Delivery culture&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Agile development has many flavours and in my experience it has been broadly about improving a team&#39;s capacity to release software by improving processes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For the team I work on, it has worked out great. We generally deliver things in good time and we work well in a productive and enjoyable environment.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Right from the very top of the business at even the board level, the whole company is focused on delivering software and features to the areas of the business who need it. In our company we have a number of departments who fight for the features they want on our main website; plus a number of other products. These requests eventually filter down to the development team and we build them.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From there, that&#39;s more or less it; &lt;em&gt;and that&#39;s the problem&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a company becomes delivery focused, it forgets that it should be &lt;em&gt;value focused&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Build - Measure - Learn&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I&#39;ve been reading Lean Startup and it focuses heavily on validating your assumptions when building products. It seems obvious really; you need to verify that the features you make actually have value.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;From my (admittedly limited) experience with agile, teams invest a lot of time in terms of reviewing processes in order to deliver things more efficiently; but it doesn&#39;t matter how efficiently you deliver a feature that isn&#39;t used; you are wasting money by doing so.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This can sometimes be a hard sell to the business. People have forged jobs for themselves by making decisions on what should be built; based on their previous successes. It takes quite a culture shift for a business to acknowledge that it&#39;s assumptions about it&#39;s customers could be wrong.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;However unless you validate your learning with actual real hard numbers, all that you are doing is guessing.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you consider how expensive software development is, guessing is &lt;em&gt;not good enough&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is not to say that we shouldn&#39;t build anything without some peer reviewed, scientific thesis. In fact, building something and learning that customers don&#39;t want a feature is actually a really valuable piece of knowledge for a business to learn about their customers.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Lean startup talks about this in greater detail and I really do encourage you to check it out.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt; So why is it technical debt too?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;We have established that building unused stuff doesn&#39;t make business sense (duh); but it has many other unintended side-effects, which I will illustrate with an example.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I am currently working on a project which is taking some useful code we have within our big-blob mothership product and trying to extract it into smaller useful services for the rest of the business.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;While doing this we invested a lot of time trying to figure out how we can refactor certain areas of functionality so that they carry on working as we break up the system.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Of course, a BA comes along who happens to look at Google Analytics and then tells us &amp;quot;oh well only a tiny percentage (like 0.0001%) of our users use that anyway&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;strong&gt;facepalm&lt;/strong&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you don&#39;t measure the success of features but leave them in the system, developers have no choice than to &lt;em&gt;treat all the features on the product equally&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Developers have to be mindful of these features when trying to change the system to meet the business&#39;s needs; and this can have a considerable cost.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I felt frustrated, and I&#39;m sure the business would too, knowing the time and effort wasted; simply because we don&#39;t know our product (and customers) well enough.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Side effects of unused features&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I am quite confident that the business realises that a number of features on the site are much less important than others; but probably think &amp;quot;well what&#39;s the harm in it being there?&amp;quot;. I shall try and debunk this line of reasoning here.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Every&lt;/em&gt; unused feature effects a businesses&#39; ability to deliver value and makes the product worse.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Build time&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Builds can often slow down the velocity of a team. For us functional tests with Selinium have often really slowed us down. Unused features are a pointless way of slowing down your build.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Refactoring&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;The best commits are the ones where you delete code as it&#39;s less code to maintain.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;These so-called harmless features can reduce the malleability of your product because every time someone wants to change code they might have a dozen tests fail for a feature no one cares about.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Additionally, developers might think that generalising code to fit a number of different features could be worthwhile effort; but what if the dev could just delete them instead?&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;More to learn and understand&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;By having lots of features in a product, it simply becomes harder to understand; this again makes it more difficult for your team to deliver. In particular when making larger changes.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Demotivating&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Knowing that you have to work with code which isn&#39;t actually useful, is a frustrating and demotivating thing for developers to face.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;On occasion we have measured some feature&#39;s success and it was really exciting to see when a feature we made was really successful.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;em&gt;Every story should be like that.&lt;/em&gt;&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Performance&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;A number of features we know intuitively (or with analytics) that are not used, are slowing down the delivery of features which are actually useful because they are on the same web page and happen to be backed by slow queries.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;UX&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Simple is good right? Why are you cluttering your search page with features no one uses? Unused features make your product harder to use and distract users from what you actually want them to do.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Moving on&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There are plenty of tools now to validate learning. Metrics are trivial to assign to features and A/B testing frameworks can help you compare features and how a certain configuration can be more beneficial than another.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Rapid prototyping is an excellent tool to quickly test a business&#39;s hypothesis before investing too much development effort and as I said, every failed hypothesis is still a positive thing for the business as it improves it&#39;s understanding of it&#39;s customers to help it make more informed decisions later down the line.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I feel with the advent of agile development, teams took on more of a responsibility for delivery in exchange for empowerment. I think the next step in the maturity of an organisation is for the people responsible for picking features to work closer with the development team; which have the tools and expertise to help them learn more about their customers and make better decisions.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you can create a learning culture within your business you can improve the motivation of your organisation, learn more about your customers and be more efficient.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Intangibles&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Things become more difficult when you are unable to measure the success of a feature reliably.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This might be because of a salesman promising X sales if feature Y is implemented on the website. The development team has little choice and makes the feature but then sometimes this &amp;quot;vital&amp;quot; feature isn&#39;t used.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This usually comes about by customers not knowing their own needs, thinking they want a feature and demanding it from a salesperson; but they don&#39;t need it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Even though the feature is unused, it still technically has given value to the business; at the customer&#39;s expense.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;But eventually, the customer&#39;s perception as to how valuable your product is, may diminish. When you base your business on these intangible things, you are running a risk.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In these cases it would be nice to try and work with the customer to try and find features that they want and that they will actually use, as chances are other customers might find them useful which could then lead to more sales than if you just left the customer with their pile of unused features.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It would be exceptionally brave to contact a customer and say:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&amp;quot;You demanded and paid for these features but we notice you haven&#39;t used them, is there any way we can make them useful to you?&amp;quot;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;but it could lead to some valuable insights about your customers and open up new opportunities.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt; Other examples of intangibles&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&amp;quot;It&#39;ll improve SEO&amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;The person purchasing is not the end user, but is buying on behalf of the users.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h3&gt;Conclusions&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Software development has almost always been trying to become more efficient. Whether it is with different programming languages, new development techniques and different styles of project management.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Producing only what is valuable is vitally important but in many domains trying to define what is valuable can be hard, but still very important. Without this understanding the business will find it hard to find new ways to appeal to customers; which is too short-term of a viewpoint.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Thankfully these techniques are widely known these days and many companies can attribute their successes to them. In Lean Startup, it discusses how Facebook really understood their users and that helped them become what they are today. I have been to talks where engineers talk about how they often experiment and hypothesise what their users will like and measure it&#39;s success.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is up to development teams to evangelise this kind of approach upwards, to show how the business can get more out of it&#39;s development; if it is willing to work more with developers.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 09 Dec 2013 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Scala - Just enough rope to hang yourself</title>
      <link>https://quii.dev/Scala_-_Just_enough_rope_to_hang_yourself</link>
      <description>&lt;p&gt;Last week &lt;a href=&#34;http://twitter.com/shinyhappydan&#34;&gt;Dan&lt;/a&gt; and I did a presentation at the &lt;a href=&#34;http://joinit.springer.com&#34;&gt;Springer&lt;/a&gt; offices for the &lt;a href=&#34;http://www.meetup.com/Functional-Media/&#34;&gt;Functional Media meetup&lt;/a&gt; about our experiences with Scala. We thought it would be interesting to talk about the mistakes we had made with Scala as we thought that would be more interesting than rehashing a number of other talks about why Scala is or isn&#39;t good.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://docs.google.com/presentation/d/1_IcQejhu8byqUMj8MFqVeN3L_EitnVxwG0WUrYV3meE/pub?start=false&amp;amp;loop=false&amp;amp;delayms=3000&#34;&gt;You can find the slides here&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Scala is a very feature rich language and because of this there are many ways of doing things. This was how Scala was designed, to allow developers to express themselves in a flexible way in comparison to languages like Java.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This flexibility is a double-edged sword and I think this not only effects our team but can also effect the OSS community around Scala. Some developers see the power in being able to write DSLs or construct cool type systems which they think will be really useful but aren&#39;t actually as generalised and good as they think and can hamstring other developers. As Jeff Atwood says &lt;a href=&#34;http://www.codinghorror.com/blog/2013/07/rule-of-three.html&#34;&gt;writing re-usable code is hard&lt;/a&gt; and that is especially true when with a flexible language like Scala.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This immediately comes to mind when I read this post by &lt;a href=&#34;http://overwatering.org/blog/2013/12/scala-1-star-would-not-program-again/&#34;&gt;Giles Alexander&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I can actually appreciate some of the author&#39;s sentiments. If I started Scala without the aid of working with some very experienced programmers in a pair programming environment I imagine I would find it a nightmare too.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;His complaints about def and val to me seem like inexperience in his team with Scala, which then means the resulting code is difficult for everyone. Again, this is Scala&#39;s flexibility hurting a team. I actually think good Scala code reads really well, but it takes some discipline and knowhow. Scala can tempt you into writing code you think looks great but is very hard for other people to read.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Lessons from our talk&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you want to have a productive team working with Scala, we feel you need&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;An enthusiastic team&lt;/em&gt; - A team that really wants to learn Scala where individuals demonstrate new powerful ways of getting stuff done to the rest of the team&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Pair programming&lt;/em&gt; - This helps newer people get up to scratch with Scala.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Code review&lt;/em&gt; - You want to encourage your team to learn how to weild Scala&#39;s power but at Springer we make sure we have weekly team code review where we go over code so everyone understands&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Question things&lt;/em&gt; - &amp;quot;The functional way&amp;quot; is not a catch-all argument winner. Leveraging Scala&#39;s power is great but readability is the most important factor in code for us.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Monitor build times&lt;/em&gt; - You cant really avoid Scala&#39;s compilation problems. But if you invest a little time with CI to measure it, you can take steps to manage it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Generalists&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;There seems to be a demand on a lot of developers to be &amp;quot;generalists&amp;quot; who know a number of languages and can be productive with them. This is a perfectly valid goal as it means developers generally have a broad and open mind about technical approach.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I&#39;m not entirely sure if Scala is well suited to this as to write &lt;em&gt;good&lt;/em&gt; Scala requires you to put effort into learning and appreciating the language. It is a power tool and it means you have to spend time to know how to use it responsibly so you can write concise, readable code.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some would say this is a bad thing, but after working with Scala for a number of years now and if I was to change language I would want to make sure I picked a language which offers the same power and flexibility of Scala; otherwise I would probably feel like I am fighting the language to get things done.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I totally understand when people accuse Scala being cryptic and bloated, but I think that mainly comes from either using a horrible library of just being inexperienced. I think the true power of Scala is that it gives me the opportunity to express the intent of my code without the need of complicated boilerplate. However, it takes time to get good at it and to be honest that&#39;s what I like about it, there&#39;s always more to learn.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 02 Dec 2013 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Chris Validation Pattern</title>
      <link>https://quii.dev/The_Chris_Validation_Pattern</link>
      <description>&lt;p&gt;After nosing through some Scala FP books I have been trying hard to write small and simple functions and then compose them together. This post will show an example of where this has taken some needlessly complex code into something terser and easier to understand.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Previously&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When getting our feet wet with Scala we would more or less still write fairly traditional OO code with some nice functional goodies mixed in.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This is one of Scala&#39;s great strengths and it creates a relatively low barrier of entry for OO programmers; but there is a wealth of cool stuff you can achieve with it without having to blow the dust off your copy of The Gang of Four.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In this scenario we are re-implementing an old piece of functionality, which is user registration validation. The old Scala code to be fair it&#39;s completely fine. It&#39;s unit testable, fairly easy to understand and gets the job done.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My colleague and I (also named Chris); when re-implementing this feature for a new shared service thought we could use our growing Scala &amp;amp; FP skills to make something a bit nicer; &lt;em&gt;and&lt;/em&gt; to show off. I think it&#39;s important not to rest on your laurels with Scala and really try new things out when possible. It&#39;s not just Java without semicolons.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The Problem&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;You wish to apply a number of validation rules against something and have a list of error messages to return eventually to a client.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;def validatePassword(password: String): Set[ErrorMessages]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;The old code&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;For the first iteration of code there was a class for validation which had one public method which took the item you wished to validate. Within the class were a number of private functions that took the item and checked to see if the item was valid and returned a sequence of errors.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The respective functions are all called at the public function and the sequences are mashed together into one sequence of errors.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class PasswordValidator{&#xA;&#xA;    private def valFunc1(password: Password): Set[Error]&#xA;&#xA;    private def valFunc2(password: Password): Set[Error]&#xA;&#xA;    etc..&#xA;&#xA;    def validate(password: Password): Set[Errors] = {&#xA;        valFunc1 ++ valFunc2 ++ valFunc3 ++ etc..&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;The problems with this are :&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The validation functions have two responsibilities, applying the business rule and then returning a collection of errors when appropriate. By coupling these responsibilities the functions become less re-usable.&lt;/li&gt;&#xA;&lt;li&gt;Imagine if the private functions were public so you could unit test them. To unit test the sub functions which contain the actual business logic, you need to check for the error message returned, rather than whether the field passes the validation or not.&lt;/li&gt;&#xA;&lt;li&gt;It doesn&#39;t look enough like a regular expression, which is how you know you are winning at Scala :)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Our Approach&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When reading most FP books, they usually emphasise the idea of creating small &amp;quot;pure&amp;quot; functions which you then compose together to achieve greater pieces of functionality.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The ultimate solution: The Chris Validation Pattern&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;As I said, the colleague I did this was also called Chris so it&#39;s not an entirely egotistical name. Anyway ...&lt;/p&gt;&#xA;&#xA;&lt;p&gt;By thinking in terms of functions as being &amp;quot;pure&amp;quot; and only having one purpose, the resulting code was created fairly organically.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The first goal was to make it so the validation functions only dealt with applying a rule and letting the caller know if it passed or not&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;type StringValFunc = (String) =&amp;gt; Boolean&#xA;&#xA;def passwordIsTooShort:StringValFunc = &#xA;    _.size &amp;amp;lt; MIN_SIZE&#xA;def passwordIsTooLong:StringValFunc = &#xA;    _.size &amp;amp;gt; MAX_SIZE&#xA;def passwordNeedsInteger:StringValFunc = &#xA;    !_.exists(_.isDigit)&#xA;&#xA;//etc..&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This means that unit testing these functions becomes very easy and not dependant on the error messages. Now that they are decoupled from any domain specific error messages; you could see how they could be refactored into something more generic, such as &amp;quot;stringIsTooShort&amp;quot;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The next task is coupling each function with an error message, which is obviously done by creating a map.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;val passwordValidation = Map(&#xA;        passwordIsTooShort -&amp;gt; TooShortError,&#xA;        passwordIsTooLong -&amp;gt; TooLongError,&#xA;        etc&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;You then simply run all the functions against the value you are testing, filter out ones that didn&#39;t pass and then take the &lt;em&gt;right&lt;/em&gt; side of the Map; which results in your list of error messages.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;passwordValidation.filter(_._1(input)).map(_._2)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Ok, so to a non-scala developer it may not be completely obvious what that line does; but if you read into it, you can see it&#39;s only really performing two operations over a map.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Granted, this isn&#39;t the most impressive piece of code but I think it illustrates well how by being really strict in the responsibility of your functions and decoupling things you can compose useful functionality elegantly.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Edit&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Thanks to &lt;a href=&#34;http://www.twitter.com/shinyhappydan&#34;&gt;Dan&lt;/a&gt; for pointing out that you can use the &lt;code&gt;values&lt;/code&gt; method of a map to retrieve the values rather than the wonky &lt;code&gt;.map(_._2)&lt;/code&gt;. I also found that &lt;code&gt;filterKeys&lt;/code&gt; can make this code more readable too.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;So, ultimate version:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;passwordValidation.filterKeys(_(input)).values&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sat, 30 Mar 2013 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Understanding Javascript Objects</title>
      <link>https://quii.dev/Understanding_Javascript_Objects</link>
      <description>&lt;p&gt;I have been reading the book &lt;a href=&#34;http://shop.oreilly.com/product/9780596806767.do&#34;&gt;Javascript Patterns&lt;/a&gt;, which is fairly easy reading and I would recommend it if you wish to understand Javascript a little better.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post will describe JS objects, which is something you&#39;ll come across when you&#39;re writing almost any kind of JS.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Objects in Javascript are essentially hash tables of key value pairs. The values can be almost anything; strings, functions, other objects, etc.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;It is worth noting that these objects are mutable which can offer some cool features but obviously has it&#39;s drawbacks. This is why understanding scope is very important because otherwise you can get some unexpected behaviour when your object gets changed by something at runtime.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Here&#39;s a basic example of this mutability, where we define an empty object and then add a property.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var person = {};&#xA;person.name = &amp;quot;Chris James&amp;quot;;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;Object literals&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Objects can be defined upfront like this with a JSON like syntax:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var person = {&#xA;    name: &amp;quot;Chris James&amp;quot;,&#xA;    sayHello: function(){&#xA;        console.log(&amp;quot;Hi, my name is &amp;quot; + this.name);&#xA;    }&#xA;};&#xA;&#xA;person.sayHello()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h2&gt;Constructor functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Although there are no classes in Javascript you can create &lt;em&gt;constructor functions&lt;/em&gt; to make objects in a standardised way which makes sense for your application.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var Person = function(name) {&#xA;    this.name = name;&#xA;    this.sayHello = function() {&#xA;        console.log(&amp;quot;Hi, my name is &amp;quot; + this.name);&#xA;    };&#xA;}&#xA;&#xA;var chris = new Person(&amp;quot;Chris James&amp;quot;);&#xA;chris.sayHello();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;h3&gt;New&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Using &lt;code&gt;new&lt;/code&gt; will implicitly &lt;code&gt;return&lt;/code&gt; the &lt;code&gt;this&lt;/code&gt; object that you create in the function. You dont need to do &lt;code&gt;var this = {};&lt;/code&gt; - that is also done for you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;In other words what happens is similar to the first example in this post where it makes a new empty object and then adds the properties defined in the function.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Most importantly, the newly created object will also inherit the &lt;em&gt;prototype&lt;/em&gt; of the function you defined.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Prototypes?&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Javascript uses prototypal inheritance. A prototype simply defines methods that an object referencing it can run.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When you try to run a method of an object, if it cannot find the method locally to the object it will then try to find it in the object&#39;s prototype.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Like most things in Javascript, prototypes are mutable which can offer some interesting (and insane) power to a programmer. You could have a bunch of widgets on a web page and based on an event, such as a user action change the functionality of &lt;em&gt;all&lt;/em&gt; of them by changing the definition of their prototype.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Returning to the Person constructor function before, I defined a function called &lt;code&gt;sayHello&lt;/code&gt;. Every time this constructor function is called and an object is made, a copy of that function will be made inside that object. This is inefficient and should be refactored to use a prototype instead.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This will potentially make unit testing easier too as you can simply create a mock object which has the prototype you wish to test.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var Person = function(name) {&#xA;    this.name = name;&#xA;}&#xA;&#xA;var chris = new Person(&amp;quot;Chris James&amp;quot;);&#xA;&#xA;chris.sayHello(); // will fail&#xA;&#xA;//The following is defined after &amp;quot;chris&amp;quot; is made&#xA;Person.prototype.sayHello = function(){&#xA;    console.log(&amp;quot;Hi, my name is &amp;quot; + this.name);&#xA;};&#xA;&#xA;//But chris will have access to it by virtue of it&#39;s prototype&#xA;chris.sayHello();&#xA;&#xA;//Prototypes are mutable...&#xA;Person.prototype.sayHello = function(){&#xA;    console.log(&amp;quot;Hola, me llamo &amp;quot; + this.name);&#xA;};&#xA;&#xA;chris.sayHello(); // Spanish!&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Therefore, if you think your object will be created more than once and has methods you should definitely consider including the functionality in a prototype to save memory.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Dont forget new&lt;/h3&gt;&#xA;&#xA;&lt;p&gt;Unfortunately forgetting &lt;code&gt;new&lt;/code&gt; will not cause any &lt;em&gt;obvious&lt;/em&gt; errors. What it will do is bind new to the application&#39;s Global object, rather than the &amp;quot;new&amp;quot; &lt;code&gt;this&lt;/code&gt; which would normally be implicitly returned. In a browser, this would be the window object; fail!&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This behaviour is fixed in the &lt;a href=&#34;http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/&#34;&gt;strict mode of ECMAScript 5&lt;/a&gt; but this is not always available so it&#39;s better to be safe than sorry.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Coffeescript constructor functions&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;If you use Coffeescript&#39;s &lt;code&gt;class&lt;/code&gt; syntax, it will take care of prototyping methods for you:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;class Person&#xA;   constructor: (@name) -&amp;gt;&#xA;   sayHello: -&amp;gt; console.log(&amp;quot;Hello #{@name}&amp;quot;)&#xA;&#xA;chris = new Person(&amp;quot;chris&amp;quot;)&#xA;chris.sayHello()&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Results in&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;var Person, chris;&#xA;&#xA;Person = (function() {&#xA;&#xA;  function Person(name) {&#xA;    this.name = name;&#xA;  }&#xA;&#xA;  Person.prototype.sayHello = function() {&#xA;    return console.log(&amp;quot;Hello &amp;quot; + this.name);&#xA;  };&#xA;&#xA;  return Person;&#xA;&#xA;})();&#xA;&#xA;chris = new Person(&amp;quot;chris&amp;quot;);&#xA;&#xA;chris.sayHello();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;However, as far as I can tell it wont protect you against not using &lt;code&gt;new&lt;/code&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Constructor functions vs Object literals&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;So it seems there are two ways to create objects but which should you use?&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you wish for an object to just contain data then you should use object literals. It is also acceptable to use object literals if you are sure that you wont make another &amp;quot;instance&amp;quot; of your object to have behaviours attached to it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you feel you will have more than one instance of your object and in particular if you wish to add behaviour and alter it across all instances then create it using a constructor function.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Wed, 26 Sep 2012 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>The Web for non-techies</title>
      <link>https://quii.dev/The_Web_for_non-techies</link>
      <description>&lt;p&gt;A number of my friends are cool enough to take an interest in what I do and even go as far as to want to try and understand it.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This post is for my less techy friends to help gain an understanding on how when you type an address in your browser that you get something useful displayed to you.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Getting the information to render a page&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;When you tell your web browser to go to a website, an awful lot happens and it all begins with something called a &lt;em&gt;&lt;abbr title=&#34;Hyper text transfer protocol&#34;&gt;HTTP&lt;/abbr&gt; request&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;A HTTP request contains the information required to get a web page from a server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Some of the information included is:&#xA;- Your computer&#39;s address, so the reciever knows where to send the information back to&#xA;- The destination address; i.e Facebook.com&#xA;- Other information required to complete the request, such as your log in details.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;This request is sent to the interwebs where it uses something called &lt;abbr title=&#34;Domain name service&#34;&gt;DNS&lt;/abbr&gt; to translate your request&#39;s address from &amp;quot;facebook.com&amp;quot; to an &lt;abbr title=&#34;Internet Protocol&#34;&gt;IP&lt;/abbr&gt; address. An IP address is synonymous to a phone number and this allows your HTTP request to be transported to a server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img class=&#34;center&#34; src=&#34;http://farm6.staticflickr.com/5315/7076029021_56400bbc66_n.jpg&#34; alt=&#34;Basic diagram of client server relationship for browsing the web&#34; width=&#34;266&#34; height=&#34;320&#34; /&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Servers&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;A server is nothing special, they&#39;re usually just like any other computer, just configured in such a way that make them suited to the task of working out what information to serve.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;When a server recieves a HTTP request it will use code written by programmers to try and understand your request and respond to it correctly.&lt;/p&gt;&#xA;&#xA;&lt;h3&gt;Examples&lt;/h3&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Show the home page&lt;/li&gt;&#xA;&lt;li&gt;Register a new user to the website&lt;/li&gt;&#xA;&lt;li&gt;Show the product information for a particular product id&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;p&gt;Along with code, servers typically store other assets required to make a website, such as images, video and often a database to store information. The aforementioned code will usually deal with working out what information to pull out of the database, or update; depending on the circumstances it has to deal with.&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;The information to be shown to you&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Ultimately the code&#39;s goal is to return you a &lt;em&gt;HTTP Response&lt;/em&gt; which will contain the information needed for your browser to display something useful to you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Usually, the information returned is &lt;abbr title=&#34;Hyper text markup language&#34;&gt;HTML&lt;/abbr&gt;. You may have heard of various dialects of HTML, such as XHTML, HTML4, HTML5. Dont get bogged down by this, they all share the same goal; to describe the information to display to the user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you right click on a blank area of a website, your web browser should have an option called &amp;quot;view source&amp;quot;. If you do this you will see the HTML used to show you your web page.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may notice things such as&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;The title of the website&amp;lt;/h1&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;HTML uses &amp;quot;tags&amp;quot; to describe different kinds of content, in this case a H1 means &amp;quot;header 1&amp;quot; or main header. H2, is &amp;quot;header 2&amp;quot;, a sub header, h3 a header below that, and so on. A p tag dennotes a paragraph.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You may also notice a tag like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;https://www.google.co.uk/images/srpr/logo3w.png&amp;quot; height=&amp;quot;95px&amp;quot; width=&amp;quot;275px&amp;quot; /&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;This tells your web browser to go to a server and retrieve an image from the web server called cat, and display it to you.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Obviously the browser has to read through the HTML first to understand what other assets, such as images it has to retrieve for you. That&#39;s why you might notice when your connection is slow that things like text render quickly but images appear later.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;img class=&#34;center&#34; src=&#34;http://farm8.staticflickr.com/7133/7076002439_a405262051.jpg&#34; width=&#34;500&#34; height=&#34;186&#34; alt=&#34;diagram1&#34;&gt;&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Making it look nice&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Most modern websites use a technology called CSS; Cascading Style Sheets. This rather fancy name is actually just a list of rules to describe how a page should look.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;They describe all aspects of style, such as the colour of particular HTML elements, their font, how big they are and where they are positioned on the screen.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;For instance if you wanted to make all h1 tags on a website red and bold, you would write in your CSS file something like:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;h1{&#xA;  color: red;&#xA;  font-weight: bold;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;To attach a CSS file to a website, it is referenced in the HTML using a special tag, just like images. When your web browser sees this tag it again goes to a server, just like it would any asset on the page and retrieve it. Once the browser retrieves the CSS file it then applies it to your page and makes it look pretty; yay!&lt;/p&gt;&#xA;&#xA;&lt;h2&gt;Javascript&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Javascript can also be attached to the HTML you recieve from a server. Javascript is code which is run on your web browser, not on a server. This is called &amp;quot;client side&amp;quot; code, as it just runs on your computer, the client.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Javascript is used to manipulate what the page displays without having to go to the server. It is usually used to make a website feel more dynamic and responsive. By doing code locally on your machine it can do things a lot quicker than going back and forth from a server.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Javascript works by changing the HTML on your browser that is being used to display information to you. For instance there could be Javascript code to update:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;The time is 8:00pm&amp;lt;/h1&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;to&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;The time is 8:01pm&amp;lt;/h1&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;Javascript has many applications, in fact new uses for it are found every day, some typical examples are&lt;/p&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Validating user input. When you fill out a form incorrectly it will often give you a warning before sending your data to the server, which would be slower.&lt;/li&gt;&#xA;&lt;li&gt;Updating the page without the need for user input. For instance, a news ticker on a sport website.&lt;/li&gt;&#xA;&lt;li&gt;Animation on a page, such as &amp;quot;show all&amp;quot; on a large list of items&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2&gt;Huh?&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;I hope this has given you an appreciation of how websites work. For my role as a programmer I am involved in both the server side code and the client side code. This means when I am writing a website I am trying to write code which understands the various requests a server gets and then doing something useful for the user.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The range of challenges this poses is quite immense and I am lucky enough that technology is going forward at a very fast pace and new ways to interract with the web are being discovered every day; so it&#39;s always fairly new and exciting. For me, making a website which is fun and easy to use is a very satisfying activity.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you have any questions please dont hesitate to contact me on &lt;a href=&#34;http://twitter.com/quii&#34;&gt;twitter&lt;/a&gt; as I do love to chat about this sort of thing :)&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Wed, 11 Apr 2012 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Coffeescript Presentation</title>
      <link>https://quii.dev/Coffeescript_Presentation</link>
      <description>&lt;p&gt;I recently presented to the team an introduction to CoffeeScript (CS). CS is a Ruby-like language which compiles into Javascript.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;You can find &lt;a href=&#34;http://tinyurl.com/d6kp5ot&#34;&gt;the presentation here&lt;/a&gt; (you may need to refresh the page a few times as google docs seems dodgy). Obviously not as good as the real thing but you&#39;ll get the idea.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The code examples I used during the presentation can be found here, if you have a browse through these you should have a good idea of the language features.:&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/CoffeeScript-snippets&#34;&gt;https://github.com/quii/CoffeeScript-snippets&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;If you are involved in any kind of web development, I encourage you to give CoffeeScript a go. It doesn&#39;t take a great deal to set it up and once you have Cake (build system like Make, Rake et al.) automatically compiling your code, it becomes just like normal Javascript development.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;I have made a basic skeleton project to get you going, with a Cake file which will automagically compile your CS into JS as you make changes.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/quii/Coffeescript-web-application-example&#34;&gt;https://github.com/quii/Coffeescript-web-application-example&lt;/a&gt;&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Simply clone that and then run&lt;/p&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;    &lt;code&gt;cake watch&lt;/code&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;p&gt;My experience with Coffeescript has been generally very positive. For Springer&#39;s innovation week I have built a pretty cool web application entirely with Coffeescript, using Node.js for the server with a MongoDb for persistence. I will blog about that soon but suffice to say being able to do the whole project in one language felt great.&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Mon, 09 Apr 2012 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>New Blog</title>
      <link>https://quii.dev/New_Blog</link>
      <description>&lt;p&gt;Welcome to my new blog! I have finally got round to finishing it off. I have had it half finished for around 6 months and today I took the plunge, tidied it up and put it on the interwebs.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;My old blog &lt;a href=&#34;http://www.purplehaze.me.uk&#34;&gt;Purple haze&lt;/a&gt; used Wordpress. This one is written myself using Ruby with Sinatra. The reason I decided to roll yet another blog was because:&#xA;- I wanted to learn some Ruby&#xA;- I felt very discouraged to customise my old blog because I really cant stand PHP&lt;/p&gt;&#xA;&#xA;&lt;p&gt;The implementation of this blog is perhaps a little weird. Rather than using a database I am using the filesystem. I write my posts using my favourite markdown editor; IA Writer and Ruby just serves up the HTML generated by markdown.&lt;/p&gt;&#xA;&#xA;&lt;p&gt;Stay tuned :)&lt;/p&gt;&#xA;</description>
      <author>Chris James</author>
      <pubDate>Sun, 08 Apr 2012 00:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>