<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://blog.mikebowler.ca/feed/agiletechnicalexcellence.xml" rel="self" type="application/atom+xml" /><link href="https://blog.mikebowler.ca/" rel="alternate" type="text/html" /><updated>2026-03-16T06:36:54-07:00</updated><id>https://blog.mikebowler.ca/feed/agiletechnicalexcellence.xml</id><title type="html">Mike Bowler | Agiletechnicalexcellence</title><subtitle>Articles on agile methods, team dynamics, psychological safety, Kanban flow, technical practices, and anything else that grabs Mikes attention.</subtitle><author><name>{&quot;name&quot; =&gt; nil, &quot;picture&quot; =&gt; nil, &quot;email&quot; =&gt; nil, &quot;twitter&quot; =&gt; nil, &quot;links&quot; =&gt; [{&quot;title&quot; =&gt; nil, &quot;url&quot; =&gt; nil, &quot;icon&quot; =&gt; nil}]}</name></author><entry><title type="html">Close those bugs</title><link href="https://blog.mikebowler.ca/2026/02/12/close-the-bugs/" rel="alternate" type="text/html" title="Close those bugs" /><published>2026-02-12T00:00:00-08:00</published><updated>2026-02-12T00:00:00-08:00</updated><id>https://blog.mikebowler.ca/2026/02/12/close-the-bugs</id><content type="html" xml:base="https://blog.mikebowler.ca/2026/02/12/close-the-bugs/"><![CDATA[<p>Do you have bugs that have been open for a long time and that are low priority? Cancel them.</p>

<p>Make the hard decision. Either we’re going to fix it and we do it now, or we aren’t and we cancel it.</p>

<p>Letting that bug sit in a backlog somewhere in the hopes that someday we’ll have the time and interest to fix it is just delusional. We’ll never have time for low priority distractions, and keeping things around “just in case” is exactly that.</p>

<p>Most companies have hundreds, and I’ve seen systems with thousands, of bugs just like this. They’re noise that distracts us. We need more focus and clarity, not more distractions.</p>

<p>Fix the bugs, or accept that we won’t, and close them.</p>

<p>Indecision is waste.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><category term="waste" /><category term="bugs" /><summary type="html"><![CDATA[Do you have bugs that have been open for a long time and that are low priority? Cancel them.]]></summary></entry><entry><title type="html">Code coverage revisited</title><link href="https://blog.mikebowler.ca/2026/02/04/code-coverage/" rel="alternate" type="text/html" title="Code coverage revisited" /><published>2026-02-04T00:00:00-08:00</published><updated>2026-02-04T00:00:00-08:00</updated><id>https://blog.mikebowler.ca/2026/02/04/code-coverage</id><content type="html" xml:base="https://blog.mikebowler.ca/2026/02/04/code-coverage/"><![CDATA[<p>I’ve had several conversations recently with people arguing that mandated code coverage numbers are a positive thing. For example <em>“all code must have 90% code coverage”</em>.</p>

<p>My argument is that code coverage is a great negative metric, in that at low values, it tells you useful things and at high values it tells you nothing. So mandating high numbers is not giving us the benefit we think it is, and in fact is often causing people to game the numbers.</p>

<p>Fresh off that, I just made a change to one of my own source files that had 100% code coverage, and no tests broke.</p>

<p>No, this was not an attempt to prove anything. I was fully expecting one or more tests to break when I did this.</p>

<p>The fact that nothing broke is quite honestly shocking as I thought this code was quite well covered. It does prove my point though.</p>

<p>Code coverage is great feedback to developers; it’s an indicator of where they should put their attention. It should never be a target.</p>

<p>Update: And to the surprise of nobody who believes in good tests, as I add more tests around this particular code to cover the edge cases that were missing, I’ve just found a bug.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[I’ve had several conversations recently with people arguing that mandated code coverage numbers are a positive thing. For example “all code must have 90% code coverage”.]]></summary></entry><entry><title type="html">Jira API: Sprints</title><link href="https://blog.mikebowler.ca/2026/01/29/jira-api-sprints/" rel="alternate" type="text/html" title="Jira API: Sprints" /><published>2026-01-29T00:00:00-08:00</published><updated>2026-01-29T00:00:00-08:00</updated><id>https://blog.mikebowler.ca/2026/01/29/jira-api-sprints</id><content type="html" xml:base="https://blog.mikebowler.ca/2026/01/29/jira-api-sprints/"><![CDATA[<p>If you’re extracting data from a scrum board then at some point, you’ll need to extract sprint data, which is stored in two different places, inconsistently.</p>

<p>Your first contact with details on sprints is likely to be in the <a href="/2024/04/09/jira-issue-history/">issue history</a>. In here, there is information about what sprints this issue is in.</p>

<p>What’s that you say? <em>“How is it possible for an issue to be in multiple sprints?”</em> If it doesn’t finish in one sprint and that sprint ends, its still considered in that one forever. Then you can add it to another sprint and now it’s in two. Repeat as often as you like for a never-ending set of sprints for a single issue.</p>

<p>I’ve seen issues that have been in over a dozen sprints because they never get finished and just keep carrying over from one sprint to the next. Yes, that’s completely dysfunctional and should never happen. Yet, it happens all the time.</p>

<p>The entry in the history might look like this.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"field"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fieldtype"</span><span class="p">:</span><span class="w"> </span><span class="s2">"custom"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fieldId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"customfield_10020"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"from"</span><span class="p">:</span><span class="w"> </span><span class="s2">"76, 79"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fromString"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint 12, Sprint 13"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"to"</span><span class="p">:</span><span class="w"> </span><span class="s2">"76, 80"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"toString"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint 12, Sprint 14"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<h3 id="field-id">Field ID</h3>

<p>The first thing you might notice is that there is a <code class="language-plaintext highlighter-rouge">fieldId</code>, which most history items don’t have. This is a reference to the custom field (in the same document) that contains more information about the sprints that are referenced. That custom field may or may not exist. If it does exist, it will list information about one or more sprints and the sprint that you care about may or not be in that list.</p>

<p>Got it so far?</p>

<p>If it does all exist, it will look something like this, and you’ll see that it contains some useful information about the sprint such as start date, end date (which isn’t what you think it is), and completed date.</p>

<p>You might think that <code class="language-plaintext highlighter-rouge">endDate</code> is when the sprint actually completed but no, that’s <code class="language-plaintext highlighter-rouge">completedDate</code>. <code class="language-plaintext highlighter-rouge">endDate</code> is the date that you anticipated closing the sprint at the time you started it. Why are there two? I assume it made sense at one point.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">"customfield_10020"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
  </span><span class="p">{</span><span class="w">
    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Scrum Sprint 10"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"closed"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"boardId"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w">
    </span><span class="nl">"goal"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
    </span><span class="nl">"startDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-03-12T01:36:46.600Z"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"endDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-03-23T17:32:42.000Z"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"completeDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-07-13T16:58:25.335Z"</span><span class="w">
  </span><span class="p">},</span><span class="w">
  </span><span class="p">{</span><span class="w">
    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">43</span><span class="p">,</span><span class="w">
    </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Scrum Sprint 11"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"closed"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"boardId"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w">
    </span><span class="nl">"goal"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
    </span><span class="nl">"startDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-07-13T17:37:23.922Z"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"endDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2025-07-25T09:33:21.000Z"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"completeDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-01-22T16:02:01.486Z"</span><span class="w">
  </span><span class="p">},</span><span class="w">
</span></code></pre></div></div>

<h3 id="multiple-sprints-at-once">Multiple sprints at once</h3>

<p>The next thing you might notice is that unlike every other history type, the from and to values allow for multiple values.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"field"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fieldtype"</span><span class="p">:</span><span class="w"> </span><span class="s2">"custom"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fieldId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"customfield_10020"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"from"</span><span class="p">:</span><span class="w"> </span><span class="s2">"76, 79"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"fromString"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint 12, Sprint 13"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"to"</span><span class="p">:</span><span class="w"> </span><span class="s2">"76, 80"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"toString"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Sprint 12, Sprint 14"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>You might think that this history entry is telling you which sprints this item has been added to or removed from and in a roundabout way, it does.</p>

<p>You can see in this sample that this issue was in sprints 76 and 77 and is now in sprints 76 and 80. It’s always talking about the current state so we can infer from this that…</p>

<ul>
  <li>It used to be in <code class="language-plaintext highlighter-rouge">76</code> and still is, so nothing changed</li>
  <li>It used to be in <code class="language-plaintext highlighter-rouge">79</code> and now it isn’t, so it’s been removed.</li>
  <li>It used to not be in <code class="language-plaintext highlighter-rouge">80</code> and now it is, so it’s been added.</li>
</ul>

<p>When you’re parsing those, it’s pretty easy to parse the <code class="language-plaintext highlighter-rouge">from</code> and <code class="language-plaintext highlighter-rouge">to</code> fields because they’re just numbers separated by commas.</p>

<p>The <code class="language-plaintext highlighter-rouge">fromString</code> and <code class="language-plaintext highlighter-rouge">toString</code> fields are harder though because it’s all concatenated text, and since commas are allowed in sprint names, you can end up with commas in the middle of a name.</p>

<p><em>“Surely they would escape the commas in the text so it can be easily parsed”</em>, you say! They do not.</p>

<p>If you want unambiguous names, you need to parse the id and use that to index into the data in the custom field above. Of course, we’ve already learned that the sprint you want may or may not be there.</p>

<p>If it isn’t there then we have a separate API to get sprints, which is great. Except that it may not be there either. We’ll get there in a moment.</p>

<h3 id="remove-before-add">Remove before add</h3>

<p>There’s a lovely gotcha where an issue can be removed from a sprint before it was ever added. This happens when the issue gets created within the sprint. Jira considers it to be in that sprint but there is no record of it being added in the history. Then if it’s removed from that sprint, you’ll see the removal all by itself.</p>

<h3 id="the-sprint-api">The sprint API</h3>

<p>This API will return all (mostly) of the sprints for the current board.
<code class="language-plaintext highlighter-rouge">/rest/agile/1.0/board/{boardId}/sprint</code></p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"maxResults"</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="p">,</span><span class="w">
  </span><span class="nl">"startAt"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
  </span><span class="nl">"total"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
  </span><span class="nl">"isLast"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"values"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w">
      </span><span class="nl">"self"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://improvingflow.atlassian.net/rest/agile/1.0/sprint/1"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"closed"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Scrum Sprint 1"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"startDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-03-26T16:04:09.679Z"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"endDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-04-09T16:04:00.000Z"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"completeDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-04-10T22:17:29.972Z"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"createdDate"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-03-26T16:03:49.814Z"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"originBoardId"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w">
      </span><span class="nl">"goal"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>I’m sure you’ve picked up by now that even this API doesn’t return all the sprints, although it often returns more here than we have in the custom field.</p>

<p>In my testing so far, it seems that it does return any sprint that actually has an issue in it. Any sprint that’s empty will not be returned, which is annoying.</p>

<h3 id="conclusion">Conclusion</h3>

<p>So in conclusion, like all the other Jira API’s, there is useful data in here but its inconsistent, incomplete, and poorly thought out.</p>

<hr />

<p>Other articles about the Jira API:</p>
<ul>

  
    <li><a href="/2024/04/07/jira-api-intro-authentication/">Intro and authentication</a></li>
  

  
    <li><a href="/2024/04/09/jira-issue-history/">Issue history</a></li>
  

  
    <li><a href="/2024/04/12/jira-api-statuses/">Statuses</a></li>
  

  
    <li><a href="/2024/04/17/jira-api-board-details/">Board details</a></li>
  

  

</ul>

<p>See also the <a href="https://jirametrics.org">JiraMetrics</a> tool, which is the reason I’ve had to learn the idiosyncrasies of the Jira API. If you just want access to the data then let JiraMetrics do it for you.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><category term="jira_api" /><summary type="html"><![CDATA[If you’re extracting data from a scrum board then at some point, you’ll need to extract sprint data, which is stored in two different places, inconsistently.]]></summary></entry><entry><title type="html">Bad documentation</title><link href="https://blog.mikebowler.ca/2025/10/25/bad-documentation/" rel="alternate" type="text/html" title="Bad documentation" /><published>2025-10-25T00:00:00-07:00</published><updated>2025-10-25T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/10/25/bad-documentation</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/10/25/bad-documentation/"><![CDATA[<p>I grew up in a large city, and when I first moved out to a small town, one of the first differences I noticed was how everyone gives directions based on how things used to be.</p>

<p><em>“You’ll turn left just past Flieler’s”</em>, where for the last twenty years it’s been called Sunoco, or <em>“turn just past where the Johnson’s used to live”</em>.</p>

<p>If you live in the community, it still works because everyone knows how it used to be. The problem is when you’re new to the community or if you’re just passing through. Then these descriptions are just meaningless or worse time-wasting.</p>

<p>I’ve been reminded of this over the last few weeks as I attempt to learn Google Ads and all the documentation is very precise in telling me where menu options used to be, and how things used to work, and is absolutely useless at telling me what I need to do today.</p>

<p>It’s all too easy when writing documentation to treat it as <em>one and done</em> work. I wrote it and won’t have to change it. Yet, incorrect documentation is much worse than no documentation. If I’m driving down the street looking for a sign that says <em>Flieler</em>, I’m going to drive right past the <em>Sunoco</em> sign and not even know it.</p>

<p>So when we write documentation for our products, we have to also consider the cost of maintaining that documentation. It will get out of date and if we don’t keep it in sync, we are wasting our clients time and money.</p>

<p>I did finally figure out how to get my ads campaign running, just as I finally did figure out how to get around that small town. It just took far longer than it should have.</p>

<p>If we’re going to call ourselves customer focused, we need to consider how much of our customers time we’re wasting.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[I grew up in a large city, and when I first moved out to a small town, one of the first differences I noticed was how everyone gives directions based on how things used to be.]]></summary></entry><entry><title type="html">Why don’t we collaborate more?</title><link href="https://blog.mikebowler.ca/2025/10/17/why-dont-we-collaborate-more/" rel="alternate" type="text/html" title="Why don’t we collaborate more?" /><published>2025-10-17T00:00:00-07:00</published><updated>2025-10-17T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/10/17/why-dont-we-collaborate-more</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/10/17/why-dont-we-collaborate-more/"><![CDATA[<p>In an office environment, it’s always been obvious when there’s a major production problem. You’ll see everyone standing around a single desk; everyone working together on the same problem at the same time. If there’s a blocker to what they’re doing, one or more people in the group will immediately do something to remove that obstacle, to ensure that the main work continues uninterrupted.</p>

<p>Everyone is hyper-focused on completing the single task in front of them and all distractions are ignored or removed.</p>

<p>Then when the emergency is over, we all drift away, back to our regular desks to work in isolation again. Typically scattering our focus across many different things, and now significantly less effective than we had been. The pressure is off so we revert to our familiar routine.</p>

<p>The above tells us that we all know how to work in a highly collaborative environment. We do know how to work together and we do it instinctively when the stakes are high, and it’s really important to get the work done quickly and correctly.</p>

<p class="key_point">We already know how to work in a really effective way, even though we rarely do.</p>

<p>So why don’t we work that way all the time?</p>

<p>First, I would be remiss if I didn’t acknowledge that some teams do work this way every day, and they get amazing results. They’re just not the majority. See teams that do <a href="/2023/04/22/ensemble-programming/">ensemble work</a> or <a href="/2021/06/19/pair-programming/">pairing</a>.</p>

<p>So why don’t we?</p>

<p><strong>It’s not rewarded:</strong> We’re not rewarded for focusing on a single thing until it’s finished. We’re rewarded instead for starting things. We’re rewarded for juggling many things at the same time. We’re <a href="/2023/05/20/busyness/">rewarded for being busy</a>, rather than effective. Worse, we’re often rewarded for putting out fires but not for preventing them.</p>

<p><strong>It’s comfortable:</strong> Working by ourselves has no social pressure. We’re not concerned about others judging how we work or what we do. As long as we look busy, we’re left alone. It’s a simple routine and routines make us feel calmer and safer.</p>

<p><strong>It’s the standard:</strong> Nobody will ask us to justify why we choose to work by ourselves; that’s the default. They might ask us to justify why we would work any other way, even when the default approach is less effective.</p>

<p>We already know how to work better. Perhaps it’s time to start doing that.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[In an office environment, it’s always been obvious when there’s a major production problem. You’ll see everyone standing around a single desk; everyone working together on the same problem at the same time. If there’s a blocker to what they’re doing, one or more people in the group will immediately do something to remove that obstacle, to ensure that the main work continues uninterrupted.]]></summary></entry><entry><title type="html">The extreme in eXtreme Programming (XP)</title><link href="https://blog.mikebowler.ca/2025/08/31/the-extreme-in-xp/" rel="alternate" type="text/html" title="The extreme in eXtreme Programming (XP)" /><published>2025-08-31T00:00:00-07:00</published><updated>2025-08-31T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/08/31/the-extreme-in-xp</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/08/31/the-extreme-in-xp/"><![CDATA[<p>My first exposure to anything Agile was with eXtreme Programming (XP) back in 1999. While it had many process steps similar to what Scrum and Kanban offer today, the thing that really differentiated XP was it’s focus on technical practices. It’s those technical practices that we are usually referring to when we talk about XP today.</p>

<p>Yet, the practices themselves weren’t intended to be end-states. They were merely the best practices that we knew about at the time, and today we know about a number that are even better. Continuous delivery and <a href="/2023/04/22/ensemble-programming/">ensemble/mob programming</a> weren’t even a thing at that time and yet they’re both completely in line with what XP advocates.</p>

<p>The really important thing about XP is really in understanding where the <em>“extreme”</em> in the name comes from. The basic idea is that if we believe that a practice or approach is good then instead of doing it a little bit, let’s turn it up to extreme levels and do it all the time.</p>

<ul>
  <li>If we think that testing is a good thing then let’s do it all the time, by writing the tests first. (<a href="/2024/01/11/tdd-as-design/">TDD</a>, BDD)</li>
  <li>If we think that talking to the customer is a good thing then let’s get them on the team so we can talk to them all the time. (Onsite customer)</li>
  <li>If we think that keeping the code integrated is a good thing then let’s do it constantly. (<a href="/2024/06/20/ci-is-not-a-server/">continuous integration</a>)</li>
</ul>

<p>When we introduce some of these practices today, we often get push-back on the specific practices, while missing the intention behind it. If you don’t like the specific practice that we’re doing, then find a different way to turn the good up to extreme levels.</p>

<p>XP is <em>“extreme”</em> because it doesn’t settle for <em>“good enough”</em>. That seems like a positive to me.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[My first exposure to anything Agile was with eXtreme Programming (XP) back in 1999. While it had many process steps similar to what Scrum and Kanban offer today, the thing that really differentiated XP was it’s focus on technical practices. It’s those technical practices that we are usually referring to when we talk about XP today.]]></summary></entry><entry><title type="html">What work to select for an ensemble</title><link href="https://blog.mikebowler.ca/2025/08/25/work-for-an-ensemble/" rel="alternate" type="text/html" title="What work to select for an ensemble" /><published>2025-08-25T00:00:00-07:00</published><updated>2025-08-25T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/08/25/work-for-an-ensemble</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/08/25/work-for-an-ensemble/"><![CDATA[<p>When I facilitate an <a href="/2023/04/22/ensemble-programming/">ensemble session</a> (also called Mob Programming) with a team, I’m often asked what work we should pick to work on. The answer is really whatever we would have done this week anyway.</p>

<p>Too many teams try to pick the “perfect” piece of work for the ensemble, and when they do, they inevitably pick something that nobody really cares about.</p>

<p>We’re not doing katas or fake examples. We’re not picking up that item that you’ve wanted to do for the last year but never got around to.</p>

<p>We’re picking something important enough that we would have done it this week anyway.</p>

<p>That could be implementing a new feature request, or fixing a bug, or performance tuning. The actual type of work doesn’t matter. What does matter is that it’s something that we care about finishing.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[When I facilitate an ensemble session (also called Mob Programming) with a team, I’m often asked what work we should pick to work on. The answer is really whatever we would have done this week anyway.]]></summary></entry><entry><title type="html">The big rewrite</title><link href="https://blog.mikebowler.ca/2025/06/25/the-big-rewrite/" rel="alternate" type="text/html" title="The big rewrite" /><published>2025-06-25T00:00:00-07:00</published><updated>2025-06-25T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/06/25/the-big-rewrite</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/06/25/the-big-rewrite/"><![CDATA[<p>I remember once having two back-to-back clients who had just rewritten significant systems in their environment. I asked why they’d chosen to rewrite the system from scratch rather than just fixing them as they were.</p>

<p>At the first, they said <em>“The old system was written in Java and Java is unusable so we rewrote it in C# and now it’s great.”</em></p>

<p>At the second, they said <em>“The old system was written in C# and C# is unusable so we rewrote it in Java and now it’s great.”</em></p>

<p>These statements can’t both be true at the same time. In fact, both Java and C# are reasonable languages and either one would have done the job. It wasn’t the language/platform that was at fault, no matter how much these companies told themselves that.</p>

<p>Does this mean that the platform is never the problem? No, there are legitimate cases, usually when we’ve built on top of proprietary vendor systems, when ongoing licensing and/or support costs from that vendor make it untenable to continue funding that code base. These cases are exceptionally rare however - I’ve seen two in my entire career.</p>

<p>What’s significantly more common is that we ignored quality in the product for so long that eventually we gave up and decided to rewrite it from scratch. We often call this <em>technical bankruptcy</em> - that point where it’s so painful to work with the existing system that we give up.</p>

<p>You might be thinking that we would never consciously choose to ignore quality and usually we don’t. It’s all those unconscious points where we prioritize something else over quality, that gets us in trouble.</p>

<ul>
  <li>Any time we defer fixing bugs in favour of shipping new features, we’re ignoring quality</li>
  <li>Any time we defer fixing technical debt, we’re ignoring quality</li>
  <li>Any time we ignore feedback from customers about usability issues, we’ve ignored quality</li>
  <li>Any time we have many items in progress (WIP) rather than staying focused on a few, we’re ignoring quality</li>
  <li>Any time we have people going off and working by themselves, rather than actively collaborating, we’re ignoring quality</li>
</ul>

<p>I’ve written about quality before, and today I want to stay more focused on the notion of a big rewrite.</p>

<p>I’ve seen cases where people are starting to talk about rewriting a system before the first system is even in production. They’ve made such a mess of the first product that they realize already that it’s not usable over the long haul and needs to be replaced.</p>

<p>Then what happens is that we rewrite the product on a new platform, and at the beginning, the new code is really easy to work with and easy to extend. However, by the time this new system is ready for production, it’s often in just as bad shape as the first system.</p>

<p>How could this possibly be? How could the new system be as bad as the one we’re replacing?</p>

<p>The simple answer is because all we changed was the code itself. We didn’t change our practices around quality. We didn’t change the way we write code. We didn’t do anything different on this second attempt than we had done on the first attempt. We might have a different design approach and a different language but all the things that led to poor quality code are still in place.</p>

<p>Since we never tried to improve the original code in place, we never developed the practices that lead to high quality code. We just did the same thing all over again, and got the same result.</p>

<p>Like the quote that is often attributed to Einstein: <em>“The definition of insanity is doing the same thing over and over again and expecting different results”</em></p>

<p>If we want better results, we need to build the skills that will lead to those better results. Throwing away a large code base and replacing it, does not teach the skills for building high quality code.</p>

<p>To develop those skills that will lead to better quality, we need to actively improve the code we have. The next time someone proposes throwing some code away and rewriting it, we need to say no. Improve it gradually instead.</p>

<p>We also need to be constantly practicing the skills of improving code. We should be refactoring constantly to improve that code, not just touching it when there is a new feature to add.</p>

<p>The <a href="/2025/06/22/scouting-rule/">Scouting Rule</a> says that we should always leave the campsite cleaner than when we arrived. Applied to software, that means always leaving the code a little bit better. Did you see some duplication? Remove it. Did you see poor variable naming? Fix it.</p>

<p>If we do this regularly then we’ll never get to the point of a rewrite. I’ve seen ten year old code bases that were a pleasure to work with, and six month old code bases that were a disaster. Consider which one you want.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[I remember once having two back-to-back clients who had just rewritten significant systems in their environment. I asked why they’d chosen to rewrite the system from scratch rather than just fixing them as they were.]]></summary></entry><entry><title type="html">Scouting rule</title><link href="https://blog.mikebowler.ca/2025/06/22/scouting-rule/" rel="alternate" type="text/html" title="Scouting rule" /><published>2025-06-22T00:00:00-07:00</published><updated>2025-06-22T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/06/22/scouting-rule</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/06/22/scouting-rule/"><![CDATA[<p>We often talk about the scouting rule of <em>“always leave the campsite cleaner than you found it”</em>, or in a software context <em>“always leave the code a little bit better than you found it”</em>.</p>

<p>If you see duplication in the code, then remove that before you leave the method. If you see poor variable names then fix those before you leave.</p>

<p>What we don’t talk about as much is how a culture of branching and Pull Requests (PR’s) actively discourages making small changes for that purpose. If I want to rename a method to make it clearer and know that making that little change is going to require real effort to go through a review process and manual merges, then I’m more likely to decide to just live with the original name, even if it is is poor.</p>

<p>Whereas if I can make that little refactoring and directly check it into mainline then it’s a very low effort change that contributes to the quality of the product. It’s become easy to do the right thing.</p>

<p>How many things do we have like this, that actively discourage us from doing the right thing?</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[We often talk about the scouting rule of “always leave the campsite cleaner than you found it”, or in a software context “always leave the code a little bit better than you found it”.]]></summary></entry><entry><title type="html">Quality</title><link href="https://blog.mikebowler.ca/2025/06/17/quality/" rel="alternate" type="text/html" title="Quality" /><published>2025-06-17T00:00:00-07:00</published><updated>2025-06-17T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2025/06/17/quality</id><content type="html" xml:base="https://blog.mikebowler.ca/2025/06/17/quality/"><![CDATA[<p>The theme for this week seems to be quality so let’s look at some different aspects of that.</p>

<h1 id="setting-the-goal">Setting the goal</h1>

<p>First of all, let’s consider what is really the goal. We often find ourselves talking about <strong>testing</strong> rather than <strong>quality</strong> and that leads us down the wrong path. Testing is not the goal and never should be.</p>

<p>Why would we focus on the wrong thing? It has to do with a psychological phenomenon called <em>attribute substitution</em>, where in an attempt to reduce the mental effort required, we replace a complex decision with a simpler decision and aren’t even aware that we’ve done so.</p>

<p>Quality is a difficult thing to get our heads around so we simplify the problem to <em>testing</em> and focus on that. Yet, most of what we call testing happens too late in the process to actually improve the quality. See this article on <a href="/2024/01/09/quality-vs-testing/">quality vs testing</a> for more.</p>

<p>The best we can hope for with typical testing is that we’ll identify when we need to go back and rework the product. If we want the testing to actually improve the quality then it needs to happen during creation of the product, not after the fact. This is the essence of techniques like <a href="/2024/01/11/tdd-as-design/">test driven development</a> where the <em>testing</em> happens before the code is even written.</p>

<p>What we normally call <em>testing</em> is an inspection step, not a quality one, and as Deming says: <em>“Inspection does not improve the quality, nor guarantee quality. Inspection is too late. The quality, good or bad, is already in the product.”</em></p>

<p>If we want to improve quality then we need to focus on quality. The moment we start talking about testing, we’ve taken our eyes off the ball.</p>

<h1 id="bugs">Bugs</h1>

<p>If you ask the typical team what a bug is, you won’t be able to get a clear answer. We talk about bugs all the time and yet we all seem to have different ideas of what they are.</p>

<p>I have a clear <a href="/2023/04/21/bugs/">three point definition for a bug</a>. I don’t insist that anyone uses my definition, but I find that many teams do, because they don’t have their own.</p>

<p>It’s a defect if:</p>
<ol>
  <li>The team knew what it was supposed to do</li>
  <li>And it doesn’t do that thing</li>
  <li>And the team said they were done</li>
</ol>

<p>All three are important. If someone insists that it’s broken because it doesn’t do something that we never talked about, it’s not a bug. If we didn’t understand what it was supposed to do, then it’s not a bug when it doesn’t do that thing.</p>

<p>Why it’s important to have a clear definition of that bug, is that every bug is a place where we said we’d finished the work and we didn’t.</p>

<p>Having it so clearly defined will change the whole conversation around prioritizing the fixing of bugs. A bug is something that we’d already prioritized, and already decided to work on but stopped before we were finished. If we’d finished it, there would be no bug.</p>

<p>So now if someone asks if we want to talk about prioritize bugs, it’s really a matter of <em>“do we want to finish this thing that we’d already decided was important enough to have started first, or do we want to do this new feature that was clearly less important because we’re only looking at it now?”</em></p>

<p>Yes, I realize that priorities change and the newer thing might really be more important, but most of the time that isn’t true.</p>

<p>When you realize that those bugs really are more important than new features, you’ve just taken the first step towards a <a href="/2024/08/15/zero-bugs/">zero defect policy</a></p>

<p>You may now be thinking <em>“What if we don’t want to fix it?”</em> Then close the bug. Why are you leaving it in the ticketing system if it isn’t important enough to finish? Yes, it really is that simple.</p>

<p>Have you ever sat in a bug prioritization meeting? You’ll never get that time back and that meeting was 100% waste. Either fix the bugs or decide that you won’t, and cancel them. Trying to prioritize one against the others is a waste of everyone’s time.</p>

<p>That last point in the bug definition of <em>“the team said they were done”</em> has one more interesting implication. We don’t ever open a bug if the story is still showing as open, which means that we can never have two tickets open for the same thing at the same time.</p>

<h1 id="pull-requests">Pull requests</h1>

<p>At many companies, Pull Requests (PR’s) are treated as if they were a quality step, and yet in the most common cases, they aren’t. PR’s are an inspection step that happens after some portion of the code is finished.</p>

<p>Can a PR be used to get feedback in the moment, to help with quality as the code is being built? Absolutely yes. Unfortunately, they’re almost never used in that way — instead they’re used for inspection and gate-keeping.</p>

<p>The common case for PR’s is that we create one and send off an asynchronous request for feedback. Then we move on to some other work because we know it will be at least hours, if not days, before we get any feedback. If we were actually using the PR for the purposes of improving quality, we’d want immediate synchronous feedback.</p>

<p>There are certainly people who use PR’s this way. Where they create the PR as a way to see all the changes in one place and then immediately review them with someone else so that they can get feedback that will then inform quality.</p>

<p>The asynchronous model, on the other hand, is a handoff. We’ve said that we’re finished and want someone else to approve it. This is now an inspection step.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[The theme for this week seems to be quality so let’s look at some different aspects of that.]]></summary></entry><entry><title type="html">SpecFlow becomes Reqnroll</title><link href="https://blog.mikebowler.ca/2024/12/21/reqnroll/" rel="alternate" type="text/html" title="SpecFlow becomes Reqnroll" /><published>2024-12-21T00:00:00-08:00</published><updated>2024-12-21T00:00:00-08:00</updated><id>https://blog.mikebowler.ca/2024/12/21/reqnroll</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/12/21/reqnroll/"><![CDATA[<p>A number of my clients use SpecFlow and this will be relevant to them. <a href="https://support-hub.tricentis.com/open?number=NEW0001432&amp;id=post">SpecFlow has been end-of-lifed</a> and replaced by <a href="https://reqnroll.net">ReqNRoll</a>.</p>

<p>I hadn’t been following this story but as I understand it, Tricentis had purchased the open source project SpecFlow back in 2020 and had been offering it as part of their lineup. They have now discontinued the project so the original authors have forked the codebase under the new name Reqnroll and will continue to support it there.</p>

<p>More background on this <a href="https://reqnroll.net/news/2024/02/from-specflow-to-reqnroll-why-and-how/">here</a>.</p>

<p>So if you’ve been using SpecFlow, it’s time to upgrade that to Reqnroll.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><category term="BDD" /><summary type="html"><![CDATA[A number of my clients use SpecFlow and this will be relevant to them. SpecFlow has been end-of-lifed and replaced by ReqNRoll.]]></summary></entry><entry><title type="html">Ensemble work feels slower, but that’s deceptive</title><link href="https://blog.mikebowler.ca/2024/11/25/ensemble-seems-slower/" rel="alternate" type="text/html" title="Ensemble work feels slower, but that’s deceptive" /><published>2024-11-25T00:00:00-08:00</published><updated>2024-11-25T00:00:00-08:00</updated><id>https://blog.mikebowler.ca/2024/11/25/ensemble-seems-slower</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/11/25/ensemble-seems-slower/"><![CDATA[<p>It’s interesting that when a team tries <a href="/2023/04/22/ensemble-programming/">ensemble work</a> (also called mob programming), it feels really slow. Slower than it actually is.</p>

<p>It’s common to hear during the debrief that people enjoyed it and that they learned something and that they feel the quality of the work was better but <em>“we went so much slower”</em>.</p>

<p>What makes that so interesting is that on the occasions that I’ve actually tracked how long we’ve taken to get the work done, it’s been at least as fast, if not faster, than if we had split the work up and had each person work individually on their part.</p>

<p>To be very clear what I’m saying, if there are four people working in ensemble, they will complete as much in a day as those same four people working individually for a day. This is really counter-intuitive for most people; we naturally assume that four people working together will only be as productive as one person working individually.</p>

<p>The most dramatic example of this was just recently with a team that completed as much work in two days as an ensemble than that same team did working individually in the following eight days. Effectively being four times as productive when in an ensemble. What makes this particular example even more astounding is that this was the first time they’d ever worked this way, and they didn’t think they were going very fast at all.</p>

<p>That example isn’t typical in my experience but what is typical is that we are at least as productive together in an ensemble than when all those same people were working individually. Yet it always feels as if we’re moving slower. Much slower.</p>

<p>So when people say that ensemble work, or pairing, is slower then I encourage you to actually measure the results. Don’t just rely on how it feels. That feeling is deceptive.</p>

<p>A couple of notes:</p>
<ul>
  <li>I always ask for two full days when introducing a team to ensemble work. If you only book a few hours, you may not see the same benefits. It needs time to get going, albeit not that much time.</li>
  <li>Ensemble work is not just a matter of getting a bunch of people together and telling them to work. There is a structure to this, <a href="/2023/04/22/ensemble-programming/">with some specific rules</a> and like anything new, this really benefits from having an experienced facilitator. If you aren’t following the structure or don’t have an experienced facilitator, it may take longer before the team starts to become productive.</li>
  <li>You may think that you’ll only get this benefit if the entire ensemble is in the same room and that’s not true. This works just as well when everyone is fully remote. The extremely productive example above was a team that was fully remote.</li>
  <li>I’ve not had great results with a hybrid environment were some are in the room and some are not and I’d advise against this. If some people are remote then treat everyone as remote and have them call in from their desks, even if they’re in the same building.</li>
</ul>

<p>I’ve introduced hundreds of teams to ensemble work over the last decade and can help your teams get started.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[It’s interesting that when a team tries ensemble work (also called mob programming), it feels really slow. Slower than it actually is.]]></summary></entry><entry><title type="html">YAGNI (You Aren’t Going to Need It)</title><link href="https://blog.mikebowler.ca/2024/09/18/yagni/" rel="alternate" type="text/html" title="YAGNI (You Aren’t Going to Need It)" /><published>2024-09-18T00:00:00-07:00</published><updated>2024-09-18T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/09/18/yagni</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/09/18/yagni/"><![CDATA[<p>YAGNI (You Aren’t Going to Need It) is a principle that keeps us from over-engineering the system. <strong>Build today only those things that you need today.</strong> Things that we need tomorrow, we can build tomorrow.</p>

<p>Yet if we apply that principle blindly, as beginners often do, we can end up painting ourselves in a corner by not looking ahead and considering what might be coming. If we don’t think about tomorrow then we might end up making decisions today that actually make tomorrow much harder than it needs to be.</p>

<p>Doing YAGNI well does require us to think, at least a little bit, about the future while only implementing today, what we need today.</p>

<p>For example, if we are building a shopping cart app, we might find that today we only need to put one item in the shopping cart. If we apply YAGNI blindly then we might implement our database with only one possible field for an item, rather than as a collection. That would require rework the moment we want to add the second item. If we think ahead for even a moment, we would realize that a shopping cart should contain a collection of items, rather than one.</p>

<p>YAGNI is an exercise in focus, not an excuse to stop thinking.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[YAGNI (You Aren’t Going to Need It) is a principle that keeps us from over-engineering the system. Build today only those things that you need today. Things that we need tomorrow, we can build tomorrow.]]></summary></entry><entry><title type="html">Hot-fixes</title><link href="https://blog.mikebowler.ca/2024/09/08/hotfixes/" rel="alternate" type="text/html" title="Hot-fixes" /><published>2024-09-08T00:00:00-07:00</published><updated>2024-09-08T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/09/08/hotfixes</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/09/08/hotfixes/"><![CDATA[<p>It used to be common that we would have two different ways to deploy something to a production environment.</p>

<ol>
  <li>
    <p>We would have the normal way, where everything went through a long testing cycle and there were checks and balances to ensure we weren’t going to break anything. It often took weeks to get through this path.</p>
  </li>
  <li>
    <p>Then there was the hot-fix approach where we tried to contain the change to the smallest possible thing and crossed our fingers that nothing would break. This allowed us to get to production almost immediately but it came with extremely high levels of risk. We’d just bypassed all of our checks and balances, after all.</p>
  </li>
</ol>

<p>I see far fewer companies relying on the high risk hot-fix approach today and that’s a significant win. We’ve largely done this through an increased focus on quality and through extensive automation of both testing and the build/deploy pipeline.</p>

<p>That results in the normal process to be sufficiently fast and reliable that there is no longer any need for hot-fixes.</p>

<p>If today, your company still can’t deploy a change to production both quickly and safely then it’s time to consider why that is.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[It used to be common that we would have two different ways to deploy something to a production environment.]]></summary></entry><entry><title type="html">Mocking frameworks</title><link href="https://blog.mikebowler.ca/2024/09/02/mocking-frameworks/" rel="alternate" type="text/html" title="Mocking frameworks" /><published>2024-09-02T00:00:00-07:00</published><updated>2024-09-02T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/09/02/mocking-frameworks</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/09/02/mocking-frameworks/"><![CDATA[<p>I’ve recently noticed a number of posts criticizing mocking frameworks, where half the responses are defending the idea of mocking rather than talking about the frameworks that had been called out<sup id="fnref:AttributeSubstitution"><a href="#fn:AttributeSubstitution" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>. Let’s be clear that those are two completely different things.</p>

<p>We can agree that mocking as a concept is useful, while strongly criticizing mocking frameworks.</p>

<p>In general, mocking as a technique is widely overused. There are situations where it absolutely makes sense and situations where it clearly does not. When it’s really easy to create mocks then we tend to create more of them than we should, and also use them inappropriately. This is where the criticism is justified IMO. Mocking frameworks makes it really easy to do the wrong thing so we do more of the wrong thing.</p>

<p>Note that when I say “mocks”, I’m using that word to describe all of mocks, stubs, fakes, spies, etc. The idea is the same across all of them.</p>

<p>What’s an example of doing the wrong thing?</p>

<p>Here’s a case where a mocking framework was used to override the getter method when we could have first just called the setter. I’ve seen this one in real code.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Using the mocking framework foolishly</span>
<span class="nc">Customer</span> <span class="n">customer1</span> <span class="o">=</span> <span class="n">mock</span><span class="o">(</span><span class="nc">Customer</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="n">when</span><span class="o">(</span><span class="n">customer1</span><span class="o">.</span><span class="na">getFirstName</span><span class="o">()).</span><span class="na">thenReturn</span><span class="o">(</span><span class="s">"Amy"</span><span class="o">);</span>

<span class="c1">// When we could have just used the object as it's</span>
<span class="c1">// already designed to be used.</span>
<span class="nc">Customer</span> <span class="n">customer2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Customer</span><span class="o">();</span>
<span class="n">customer2</span><span class="o">.</span><span class="na">setFirstName</span><span class="o">(</span><span class="s">"Bob"</span><span class="o">);</span>
</code></pre></div></div>

<p>I’ve seen codebases with dozens of lines of mocking setup for each test, simply because they could. The developers gave no thought to how to decompose the application into more testable pieces because the mocking framework made it too easy to continue supporting a poor design.</p>

<p>You may be thinking that we shouldn’t be blaming the tool, and there is some truth to that.</p>

<p>Unfortunately, these are tools that encourage sloppy thinking and lazy design and that’s a real problem. We need more thinking, not less, and tools that encourage the wrong things are a problem.</p>

<p>Mocking is a useful technique to have in your back pocket. It’s not a technique that we should use blindly, without thinking.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:AttributeSubstitution">
      <p>This is an example of a psychological phenonomenon called <a href="/2023/12/27/attribute-substitution/">Attribute Substitution</a> where we are faced with a computationally difficult decision, we will often substitute a more easily calculated decision in it’s place and answer that instead, without even realizing that we did this. <a href="#fnref:AttributeSubstitution" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[I’ve recently noticed a number of posts criticizing mocking frameworks, where half the responses are defending the idea of mocking rather than talking about the frameworks that had been called out1. Let’s be clear that those are two completely different things. This is an example of a psychological phenonomenon called Attribute Substitution where we are faced with a computationally difficult decision, we will often substitute a more easily calculated decision in it’s place and answer that instead, without even realizing that we did this. &#8617;]]></summary></entry><entry><title type="html">“Everything that’s old is new again”</title><link href="https://blog.mikebowler.ca/2024/08/26/everything-old-is-new-again/" rel="alternate" type="text/html" title="“Everything that’s old is new again”" /><published>2024-08-26T00:00:00-07:00</published><updated>2024-08-26T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/08/26/everything-old-is-new-again</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/08/26/everything-old-is-new-again/"><![CDATA[<p>When we look at the agile technical practices, there’s a tendency to believe that these things are new and unproven and nothing could be further from the truth.</p>

<p>Test Driven Development (TDD) has been around since at least the 1950’s. There’s a paper written for a NATO conference in the 1950’s that describes this technique. It doesn’t used the words “test driven development” but does describe the approach.</p>

<p>Pair programming has been in use since the early days of the mainframe. Admittedly, they weren’t using it for the same reasons we are today, but it was in use. Back then the cost of the computer was so much more expensive than the cost of the humans that we paired people up for cost savings.</p>

<p>Mob programming is fundamentally the same approach that we’ve used for decades when we fire-fight production issues. Everyone comes together and works on the same problems at the same time. The only thing that’s different is that we’re now continuing to use the technique after we’ve put out the fire.</p>

<p>I was personally using feature flags in the 1990’s and they weren’t a novel idea at that time. They weren’t as fancy as what we have today but we implemented the same approach.</p>

<p>Trunk based development was the norm before Git came along. Creating multiple branches was possible with earlier version control systems but it wasn’t commonly used. Some might argue that starting to use branches was an improvement but that’s highly debatable in general and I personally disagree.</p>

<p>Continuous integration and continuous delivery have been around at least since the mid-1990’s, although the latter didn’t start to become popular until about 2010.</p>

<p>None of this is new. All of these techniques have been around for decades and have a proven track record.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[When we look at the agile technical practices, there’s a tendency to believe that these things are new and unproven and nothing could be further from the truth.]]></summary></entry><entry><title type="html">Ability to deliver quickly</title><link href="https://blog.mikebowler.ca/2024/08/18/ability-to-delivery-quickly/" rel="alternate" type="text/html" title="Ability to deliver quickly" /><published>2024-08-18T00:00:00-07:00</published><updated>2024-08-18T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/08/18/ability-to-delivery-quickly</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/08/18/ability-to-delivery-quickly/"><![CDATA[<p>I was talking to a team that maintained a year-end batch process. Their code only ran once a year, on the first day of the new fiscal year.</p>

<p>When I talked to them about improving their delivery process, they assured me that they had no need for that. <em>“We only deploy once a year so it doesn’t matter how long it takes to test or how long to deploy the code into production.”</em></p>

<p>So I asked them what would happen if on that one day that their code ran, they found a critical bug. <em>“Would it be ok if you waited until the following year to try again, or do you need to try again immediately?”</em></p>

<p>That’s when it became obvious to them that their ability to get changes into production quickly was just as important for them as it was for a team that deployed multiple times a day.</p>

<p class="key_point">Being able to get changes into production quickly and safely is important for every team, no matter how often you want to actually do it.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[I was talking to a team that maintained a year-end batch process. Their code only ran once a year, on the first day of the new fiscal year.]]></summary></entry><entry><title type="html">How developers and testers think</title><link href="https://blog.mikebowler.ca/2024/08/16/how-devs-testers-think/" rel="alternate" type="text/html" title="How developers and testers think" /><published>2024-08-16T00:00:00-07:00</published><updated>2024-08-16T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/08/16/how-devs-testers-think</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/08/16/how-devs-testers-think/"><![CDATA[<p>One of the first times I’d seriously paired with a tester on code, we were working on some date/time logic.</p>

<p>He first suggested that we test with Leap Day (Feb 29) as testing with an edge case like this can uncover some subtle bugs. I’d been bitten by bugs like that before and had known to test for this particular one.</p>

<p>Then for the next test, he suggested that we test with 2:00am and I was puzzled by that. Why 2:00am?</p>

<p><em>“Because not every day has one”</em>.</p>

<p>If you’re a typical developer, you may be scratching your head right now. If you’re a typical tester, you know immediately what I’m talking about. Not every day has one.</p>

<p>Good developers and good testers think differently. They approach the problem from different angles, and find different kinds of problems. We need both perspectives to really ensure quality.</p>

<p>That’s not to say that one person can’t learn to see the problem in both ways. We absolutely can and we should. The trick is that the two ways are different and each of us has a preference for one over the other.</p>

<p>If you haven’t figured out the 2:00am yet, it’s daylight savings. Once a year a day doesn’t have one at all and once a year a day has two of them.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[One of the first times I’d seriously paired with a tester on code, we were working on some date/time logic.]]></summary></entry><entry><title type="html">Zero Bugs (Defects)</title><link href="https://blog.mikebowler.ca/2024/08/15/zero-bugs/" rel="alternate" type="text/html" title="Zero Bugs (Defects)" /><published>2024-08-15T00:00:00-07:00</published><updated>2024-08-15T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/08/15/zero-bugs</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/08/15/zero-bugs/"><![CDATA[<p>For many people, the notion of Zero Bugs seems like an unsustainable dream and yet the teams that do it are tremendously successful.</p>

<p>What do we really mean when we say Zero Bugs?</p>

<p class="key_point">Zero Bugs is a policy where we have decided that if a bug is found, fixing that will be the team’s top priority. That we will not start new feature work if there are known bugs in the system.</p>

<p>Terminology: Some teams will say that defects and bugs are different things. I consider them to be the same. Anywhere I say <em>“bug”</em>, you can freely substitute <em>“defect”</em>.</p>

<p>People often jump to the conclusion that we mean <em>“our product has no bugs”</em> and that is likely impossible and certainly not what we’re saying. Having said that, if the team has been following a Zero Bug policy for a while, it’s likely that there are very few bugs left in the system anymore.</p>

<p class="key_point">I’ve seen multiple teams for whom <em>“we haven’t had a bug reported in production in years”</em> is a reality.</p>

<p>A common question is <em>“what if the business doesn’t want the team working on these bugs?”</em></p>

<p>Consider that every bug is actually unfinished work. We had implemented some feature in the past and the fact that it’s not working properly now means that we didn’t finish that work. Had we finished it, it would now be working.</p>

<p>So what we’re really asking is <em>“what if the business doesn’t want us to finish that feature that they’d previously asked for?”</em></p>

<p>If they’re happy with the existing behaviour then it’s no longer a bug so close the ticket. If it is a bug then finish it.</p>

<p>The key point is that if they want it fixed, we fix it now, not later.</p>

<p>“What if we have hundreds of open bugs right now? We can’t possibly stop everything to fix them all!”</p>

<p>If you have hundreds of bugs open then likely your team is seriously demotivated by that fact. They have also probably stopped caring about the quality of the product. If so much is already broken and nobody cares about that, why would I care if another bug slips through. This is known as the <a href="https://www.artima.com/articles/dont-live-with-broken-windows">broken window</a> effect.</p>

<p>Go through the list of bugs you have and make a decision about each. Either decide you’re going to fix it or delete it. If you’re going to fix it then do it now.</p>

<p>The teams that I’ve worked with that implemented a Zero Bug policy, tended to be happier and more productive than teams that didn’t. This should be the standard and it baffles me that anyone pushes back on it.</p>

<p>See also: <a href="/2023/04/21/bugs/">Definition of a bug</a></p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><category term="bugs" /><summary type="html"><![CDATA[For many people, the notion of Zero Bugs seems like an unsustainable dream and yet the teams that do it are tremendously successful.]]></summary></entry><entry><title type="html">Premature optimization</title><link href="https://blog.mikebowler.ca/2024/08/13/premature-optimization/" rel="alternate" type="text/html" title="Premature optimization" /><published>2024-08-13T00:00:00-07:00</published><updated>2024-08-13T00:00:00-07:00</updated><id>https://blog.mikebowler.ca/2024/08/13/premature-optimization</id><content type="html" xml:base="https://blog.mikebowler.ca/2024/08/13/premature-optimization/"><![CDATA[<p>In the early days of Java, I recall reading a book talking about performance characteristics of various things in Java. One of the tidbits that I latched onto was the suggestion that the default size of a <code class="language-plaintext highlighter-rouge">Hashtable</code> object was inefficient if it had to grow in size beyond the default.</p>

<p>As I recall the situation, the default size of a <code class="language-plaintext highlighter-rouge">Hashtable</code> was 101 and the hashing algorithm that was being used relied on the size being a prime number. It was faster for prime sizes than for non-prime. 101 is prime and so it provided good performance. If the <code class="language-plaintext highlighter-rouge">Hashtable</code> needed to be resized ever and ever larger, it very quickly became a non-prime number and performance would degrade.</p>

<p>The advice that the book recommended was to start with an initial size of 89 as starting from there would yield prime values for many more resizings as the collection became larger.</p>

<p>This notion appealed to me, so for years I littered my code with <code class="language-plaintext highlighter-rouge">new Hashtable(89)</code> instead of just <code class="language-plaintext highlighter-rouge">new Hashtable()</code>. Clearly this is better, right? Wrong.</p>

<p>At some point (I think Java 5), they re-implemented the Hashtable class and the new algorithm favoured a size that is a power of two.</p>

<p>Had all my code called <code class="language-plaintext highlighter-rouge">new Hashtable()</code>, I would have got a nice speed increase right out of the box. For no extra work, my code would be better. But my code didn’t do that. I’d decided to be clever and had hard coded it to 89, which is very much not a power of two.</p>

<p>This is a perfect example of premature optimization. Had I focused on leaving my code maintainable and easy to read, it would have improved as the libraries improved. Instead, I had decided to be clever and actually made things worse. The interesting thing is that I didn’t make it immediately worse, I’d left a time bomb that would make it worse when the code was upgraded to a newer version of Java.</p>

<p>Learn from my mistakes. Don’t optimize the code until you have a measurable performance problem. Until that point, write maintainable code, not clever code.</p>]]></content><author><name>Mike Bowler</name></author><category term="agiletechnicalexcellence" /><summary type="html"><![CDATA[In the early days of Java, I recall reading a book talking about performance characteristics of various things in Java. One of the tidbits that I latched onto was the suggestion that the default size of a Hashtable object was inefficient if it had to grow in size beyond the default.]]></summary></entry></feed>