Published Work · Articles
Written for Red Hat's Opensource.com, the WorkSafeBC Technical Blog, Redgate's Simple Talk, freeCodeCamp, and DevPro Journal between 2016 and 2024, covering test-driven development, mutation testing, refactoring under real constraints, and the discipline of shipping in small, safe steps.
April 29, 2022
Networks are unreliable and failure is inevitable, so services should be built to expect it. Argues for simple services that talk asynchronously through message passing rather than shared state, with faults isolated so one failure cannot cascade.
July 17, 2021
Identifies five categories of waste in software delivery — defects, idling and waiting, overproduction, overprocessing, and activity that never reaches a user — and shows how test-driven development attacks each one.
July 16, 2021
Software should be open for extension but closed for modification. A stable interface between a service and its clients lets you rework the implementation freely without breaking the handshake anyone depends on.
July 5, 2021
Extracting methods is the safest way into unfamiliar code. Breaking long functions into small, well-named pieces makes legacy systems testable and readable without having to understand the whole thing first.
June 11, 2021
HATEOAS decouples clients from servers by delivering the instructions for what to do next inside the response itself. Clients stop needing advance knowledge of server structure, which is what makes tightly coupled designs so brittle.
November 18, 2020
Replaces frozen requirements with hypotheses. Teams state something measurable, build the smallest thing that tests it, collect telemetry, and let the result decide — delivering value rather than merely shipping working software.
March 16, 2020
Uses mountebank service virtualization to simulate repeated login failures, showing how to configure response buffers for successive attempts and why these particular tests have to run in order rather than in parallel.
March 6, 2020
Waterfall freezes the specification and postpones integration to the end, which is premature optimization. Agile embraces risk and pulls feedback forward, surfacing problems while they are still cheap to fix.
February 17, 2020
Writing the test first separates two concerns that get tangled otherwise: deciding what should happen, and deciding how to build it. Measure twice, cut once — the carpentry rule applies to software too.
January 27, 2020
TDD belongs to unit testing of small, independent components, not to integration or system tests. Uses a car battery analogy to explain why isolating a unit from its dependencies is what makes the feedback fast enough to be useful.
October 23, 2019
TDD works through iterative micro-failures, each one returning immediate feedback. Covers the FIRST principles — fast, independent, repeatable, self-validating, thorough — and how SOLID design keeps components cheap to change.
Five parts from February 2021 built around the ZOMBIES acronym: Zero, One, Many, Boundary behaviors, Interface definition, Exercise exceptional behavior, Simple scenarios and simple solutions. One shopping-basket API, grown a step at a time.
Part 1 · February 1, 2021
Introduces the acronym and the case for small batches over long isolated coding sessions. Starts at Zero: the simplest hard-coded case, which gives immediate feedback and a foundation the rest of the tests can stand on.
Part 2 · February 2, 2021
One and Many. Moving from the empty case to a single item to multiple items demonstrates stepwise refinement, and shows how to avoid the premature complexity that conditional logic invites.
Part 3 · February 3, 2021
Boundary behaviors and Interface definition. Prevents invalid states such as a negative item count, and pins down what the API actually promises: adding items, removing them, and totalling the basket.
Part 4 · February 4, 2021
Exercising exceptional behavior. Encodes a real discount policy — ten percent off orders above $500 — as executable tests, so the business rule lives in something that runs rather than in ambiguous documentation.
Part 5 · February 5, 2021
Simple scenarios, simple solutions. Closes the series by running mutation testing against the finished API, showing how precise edge-case expectations close the gaps that remain in apparently working logic.
A 2019 series that builds a home-automation cat door in C# and xUnit, then turns the Stryker mutation testing framework loose on it to find out what the tests were never really checking.
Part 1 · August 9, 2019
Frames TDD as natural selection: iterate against a measurable test and a workable solution emerges regardless of where you started. Mutation testing is the next step, because it checks whether those tests are worth anything.
Part 2 · September 23, 2019
Starts the cat door with a failing test and lets planned failure drive each refinement. Shows how to deal with dependencies from the outset instead of discovering them later.
Part 3 · September 24, 2019
A failing test exposes a hidden dependency on system time. Separation of concerns and inversion of control turn untestable code into something deterministic.
Part 4 · September 25, 2019
Builds the abstraction out with interfaces and fake implementations, driving the door from daylight or darkness, with every step arrived at through a test written before the code.
Part 5 · September 26, 2019
Stryker alters each line of code and re-runs the suite. Surviving mutants mark logic no expectation ever covered — the gap between a green suite and a suite that means something.
Opensource.com stopped publishing in 2023, but the archive remains online — the complete run lives on my Opensource.com author page.
A two-part argument for test-driven development, written for Redgate's Simple Talk — first the case for automating the feedback, then the case for why the feedback has to be fast.
Part 1 · June 5, 2023
Programming asks you to hold two incompatible concerns at once: making the code behave, and making it well structured. TDD separates them — write the sloppy version that works first, and let an automated test replace the eleven manual steps of compile, deploy, log in, and click through.
Part 2 · February 1, 2024
Code-as-text gives you nothing back. A woodworker feels the material push back on every cut; a developer can edit for hours before the machinery reacts at all. That latency is where the waste lives, and fast automated feedback is what closes it.
Four articles for freeCodeCamp — one on the mechanics of test-driven development, three from 2016 on interfaces, protocols, and what automation quietly hands back to the user.
June 11, 2020
"Tests first" gets misread as writing the whole suite up front, which is waterfall wearing agile clothes. Write one test, make it pass, refactor, repeat — worked through a small .NET Core and xUnit example.
April 21, 2016
Bots don't need sophisticated conversation, they need a protocol. Pilots and air traffic controllers, travellers and border officers — constrained, predictable message exchange is what makes communication reliable, and the same constraint is what makes a bot work.
April 9, 2016
Automation retired the telephone operators, the elevator operators, the travel agents — and quietly handed their work to us. Self-serve was sold as liberation and delivered a second job. Argues that conversational agents are how that work gets taken back.
March 2, 2016
Traces the human-computer interface from punched cards to terminals to the desktop metaphor, and argues the GUI grew as arcane as the syntax it was meant to replace. Text was always the intuitive part; the graphics were training wheels.
Forty-seven posts written between 2020 and 2022 while serving as Software Development Practice Lead in WorkSafeBC's DevOps department — the working record of introducing technical excellence inside a large organization, from TDD and refactoring to queueing theory, systems thinking, and the ceremonies built to spread it.
January 25, 2022
Every hour of operations has a calculable cost, and work-about-work — status meetings, handoff documents, coordination overhead — burns it without producing anything. Real-time collaboration removes the need for most of it.
January 24, 2022
Three years as WorkSafeBC's Software Development Practice Lead, framed honestly as a sales job: the mandate was to raise the technical bar, and the hard part was never the technique.
January 11, 2022
Organizations measure outputs because outputs are easy to measure. High utilization rates and big batches destroy exactly the delivery predictability that leadership is asking for.
January 5, 2022
A programmer in Notepad can work undisturbed for hours; move to a real editor and it interrupts constantly. Those interruptions are feedback, and staying open to them is the humble approach.
December 30, 2021
Software engineering splits into envisioning, creating, releasing, and running — traditionally four departments with handoffs between them. DevOps is what it looks like when all four get attention simultaneously.
December 23, 2021
Gated phases and quality inspection gates generate retries, and retries are pure waste. Small batches with limited work in progress are what stop the queue forming in the first place.
December 15, 2021
Everyone is busy and yet few things are ever finished. Traces unpredictable delivery to queueing and looping rather than to bad estimates — which is why speeding up development need not speed up delivery.
December 10, 2021
Roadmaps assume predictable, hazard-free terrain. In a world that offers neither, a sea chart is the honest instrument: it marks the hazards and leaves the route to the navigator.
December 2, 2021
Debugging is what you do when you have no automated expectation to tell you what went wrong. Write the test first and the debugging session never has to happen.
November 23, 2021
Lessons from a dotcom CTO role that ended when the funding did in April 2001. Maximizing utilization feels productive and drives the team into a wall; an empty plate is not the same as finished work.
November 17, 2021
Value is what customers will pay for — a definition that works for manufacturing and breaks down for product development, where nobody knows what is valuable until it is in front of them.
November 12, 2021
Weinberg's soda machine: administration removed it to stop students congregating, and the helpdesk queue promptly got longer. On the informal collaboration that never appears on an org chart.
November 12, 2021
Terms of reference for running Townhall events — a super-event meant to build systems thinking and dismantle the barriers between silos, including how to recognize when to stop holding it.
November 11, 2021
How to start, run, and terminate a Dojo. Hands-on skills stick when acquired through immersive practice rather than presentations, and the event series itself is framed as a hypothesis to be tested.
November 9, 2021
Separates exploratory testing, which deliberately disrupts the status quo, from automated testing, which underwrites continuous delivery — and shows why only the deterministic kind can gate a pipeline.
November 4, 2021
Three kinds of automated test: customer-facing functionality, code structure quality, and systems operations. Automating an operation without automating its tests is the risky half of the job.
October 27, 2021
Quality of design is about code structure, which no end user ever sees. Walks through the industry standards and principles that keep that structure from quietly degrading.
October 25, 2021
The Dreyfus model runs from Novice to Master, but it is entirely possible to stall partway and mistake the plateau for the summit. How to notice you have stopped moving.
October 15, 2021
Behaviour and structure are inseparable, but only behaviour is visible to end users, so structure gets starved. Caring less about specific details is what makes refactoring possible at all.
September 16, 2021
A board and sticky notes are easy to acquire; knowing what to put on them is the hard part. POPCORN Flow tracks problems, options, and experiments rather than just tickets.
September 10, 2021
Alistair Cockburn's pizza parlour worked through: two windows, one facing customers and one facing the kitchen, and the parlour does not care who is standing at either.
August 25, 2021
A career spent being asked to estimate activity and then being tracked against that estimate. Makes the case for measuring outcomes instead of activities and outputs.
August 18, 2021
A lean test suite is a feature, not an accident. Demonstrated from a TDD Dojo session: tests that no longer discriminate between right and wrong should be deleted, not kept for comfort.
August 5, 2021
Flow state is productive and also a way of hoarding all the context in one person's head. Knowledge has to move through a team faster than that for delivery to stay continuous.
July 27, 2021
TDD is more than a quarter century old and still the unloved foster child of software engineering, with no conference of its own. An account of starting one.
July 22, 2021
The urge to envision a perfect design up front assumes we are building standardized confectionery. Design is not a static construct — it evolves through refactoring as the code keeps changing.
July 13, 2021
Notes from a Navigating the Future session with guest speaker Ben Ford on Boyd's Observe-Orient-Decide-Act loop, and what it has to do with DevOps feedback cycles.
May 28, 2021
Users now expect rich in-browser functionality, but the browser remains an untrusted computing environment. Every increment of client-side expressiveness buys a security problem.
May 12, 2021
What 'extreme' actually stands for in Extreme Programming: extreme interruptibility and extreme steerability. Waterfall, once rolling, offers no option but to run at the deadline.
May 7, 2021
Inspired by John Cutler's research. Staggered starts and staggered finishes are what create queues and loops; moving through the work together is what removes them.
April 29, 2021
The only reason to change software is to test a hypothesis, and a hypothesis cannot be tested until it is deployed. Introduces a working group premised on scripting every operation still done by hand.
April 22, 2021
From writing COBOL monoliths on IBM midrange machines in 1990 to the present. What makes a design good is not its elegance but whether it can still be changed.
April 8, 2021
Dijkstra retired the go-to statement 53 years earlier. Duplicated conditional logic that has to be kept in sync across a codebase deserves exactly the same treatment.
March 31, 2021
XP as Kent Beck's political statement. In the mid-1990s quality was being outsourced to QA departments, and Beck's objection was that quality belongs to everyone who touches the code.
March 26, 2021
Code is read more than ten times as often as it is written, and text remains the only way we know to program machines. On the latency code-as-text imposes and why it needs closing.
March 19, 2021
People routinely use the two words interchangeably. A visual walk-through of why iterating and incrementing are genuinely different processes with different failure modes.
March 5, 2021
CI/CD workflows should be changed only through YAML in source control, never through a GUI. Configuration that is not versioned is configuration nobody can review or roll back.
February 19, 2021
WorkSafeBC DevOps' 100th sprint happened to land on the Agile Manifesto's 20th anniversary, marked by hosting original signatory James Grenning.
October 24, 2020
The principle of least knowledge. Tight coupling is the most frequent cause of unchangeable code, and value that is expensive to change turns from an asset into a liability.
October 22, 2020
Functionality is the asset a business invests in, and the team is collectively responsible for it — which makes individual code ownership an obstacle rather than a form of accountability.
October 19, 2020
Taleb on small breakages preventing large ones. Monoliths are brittle precisely because they have no internal boundaries; simple isn't easy, but it is the only route to anti-fragile systems.
October 16, 2020
Thirty years of modifying legacy code distilled into a habit: skim rather than fully comprehend, find the region that matters, then extract methods behind micro tests.
October 15, 2020
Software built the way high-rises are: budget, signed blueprints, brick-laying, then inspection at the end. The longer the wait between deployments, the more risk accumulates unseen.
October 13, 2020
Building a feature without formulating a hypothesis is shooting in the dark. An MVP is not a small product, it is an experiment, and market leaders have largely stopped running projects.
October 3, 2020
Engineers prefer stability because complexity breeds brittleness. But fixing on a City on the Hill and refusing to change course is the more expensive bet.
September 17, 2020
TDD feels restrictive and counterproductive at first, the way marathon training hurts before it helps. An honest account of the adjustment period and what is on the other side of it.
September 4, 2020
Branching is poor man's modularization. Replaces physical modularity with logical modularity by hiding unfinished work behind feature flags instead of stashing it in branches.
A practitioner's checklist for teams shipping and monetizing a public API.
June 20, 2023
Eleven practices for building an API people actually want to use rather than one that is cumbersome and prone to breaking. Covers semantics — nouns over verbs, endpoints that name resources, JSON over XML — alongside SSL, filtering and pagination, versioning, living documentation, the principle of least astonishment, avoiding breaking changes, and keeping the internal structure from leaking through the interface.
The writing is the cheapest way to pressure-test how I think before putting anything on a calendar.
Book a Diagnostic →