IEEE Software - The Pragmatic Designer: Testing Numbs Us to Our Loss of Intellectual Control

To be published in IEEE Software in 2020.

ABSTRACT: Software teams need a healthy balance of both intellectual control, which comes from reasoning, and statistical control, which comes from testing. Complexity is the enemy of reasoning; efforts to maintain intellectual control tend to push complexity down. In my experience, many teams let their intellectual control atrophy, then compensate with more testing. This approach works for a while, but without intellectual control to keep complexity down, progress becomes slower and more difficult. Once lost, intellectual control is expensive to recover, so the teams find themselves in a local maximum they cannot escape.

[Read More]

IEEE Software - The Pragmatic Designer: Better Code Reviews with Design by Contract

This column was published in IEEE Software, The Pragmatic Designer column, Nov-Dec 2019, Vol 36, number 6.

ABSTRACT: Design by contract is a technique that improves the quality of your team’s code. It yields code with both a logical and a procedural nature, where the contracts state declaratively what will happen, and the implementations procedurally cause the desired effect. The team can reason either logically, by using the contracts, or procedurally, by following the code line by line, but the former allows them to reason about far larger programs. It also creates conditions for deliberate practice, so developers using design by contract will grow their design skills faster.

[Read More]

IEEE Software - The Pragmatic Designer: Healthy Code Reveals the Problem and Solution

This column was published in IEEE Software, The Pragmatic Designer column, Sep-Oct 2019, Vol 36, number 5.

ABSTRACT: Source code reveals abstractions from two places: the problem and the solution. It’s easier to design and evolve a system when you understand each of them separately before you combine them in code. With skill, it’s possible to separate those concerns in the code. Declarative understanding of the abstractions is the most useful and easy to convey. However, current software development processes rarely guide developers to do this.

[Read More]

IEEE Software - The Pragmatic Designer: Scale Your Team Horizontally

This column was published in IEEE Software, The Pragmatic Designer column, July-August 2019, Vol 36, number 4.


Not so long ago, when your company became successful, you bought a bigger computer to run your software. We called this scaling vertically. Today, that is less common, in part because we have gotten quite good at scaling horizontally, so when your company becomes successful it buys more of the same size computers.

This article discusses a related idea, that we should scale our teams horizontally instead of vertically. When we add another computer to our data center, we get that much more power. We’d like to add an engineer to our project and have our team get that much more power. And when our team inevitably loses an engineer, it should not be a crisis.

[Read More]

IEEE Software - The Pragmatic Designer: Principle of Least Expressiveness

This column was published in IEEE Software, The Pragmatic Designer column, May-June 2019, Vol 36 number 3.


I’m always delighted to discover a connection between two ideas that I’m already fond of on their own, so I’d like to share a connection I found recently. The first idea is writing code that expresses my thinking about the problem domain, and the second is the principle of least expressiveness (PLE). The connection is that I can use the PLE to reveal my thinking about the problem domain, and because all ambiguity stops at the code, the act of programming using the PLE can help me simplify and debug the flawed ideas I have in my head.

The PLE [3] is as follows:

When programming a component, the right computation model for the component is the least expressive model that results in a natural program.

The least expressive model means that if you can express your idea with a constant, use that, and similarly for lookup tables, state machines, and so on. You should only use a Turing-complete language when you cannot use something simpler—with the caveat not to contort the code.

[Read More]

IEEE Software - The Pragmatic Designer: Ignore, Refactor, or Rewrite

This column was published in IEEE Software, The Pragmatic Designer column, 21 February 2019, Vol 31 number 2.


Imagine that you have some code written, but it has problems. The problems are small enough that you could imagine rewriting the code completely, and you must choose what do. You could do nothing (ignore it), make incremental changes (refactor it), or write new code from scratch (rewrite it). How do you choose? What factors do you consider?

There’s already a lot of guidance. In fact, the very existence of refactoring on the list of choices is special because the idea of refactoring code wasn’t well formed until the 1990s. When you refactor code, you make changes that improve its structure but do not change its visible behavior, and our tools are increasingly good at supporting refactoring, helping us make sweeping changes safely.

Most of the guidance applies to smaller chunks of code and decisions implemented in hours or days, not weeks or months. I’ve long wished that there were a great book on architecture-scale refactoring with distilled wisdom and case studies of successes and failures. This article only touches on that but it covers some topics that augment the good advice you will find in Martin Fowler’s Refactoring book [1] and Michael Feathers’ Working Effectively with Legacy Code [2]. For a good case study of architecture evolution and decision making, I suggest Tony Tsakiris’s article [3] in which he describes how Ford looked at its vehicle control interfaces across many car brands and how it chose to embrace, tolerate, or deprecate each of them.

[Read More]

IEEE Software - The Pragmatic Designer: Intellectual Control

This column was published in IEEE Software, The Pragmatic Designer column, 14 January 2019, Vol 31 number 1. It reached the home page of Hacker News but got few comments.


In the early days of software engineering, Edsger Dijkstra warned us not to let the size and complexity of our programs cause us to lose “intellectual control” due to the limited nature of our minds. To my knowledge, he never defined precisely what intellectual control was. Our software today is staggeringly larger than the programs of the 1960s, so does that mean we have it under our intellectual control, or did we find ways to make progress without Dijkstra’s high standards?

I see signs that we have some software that is under intellectual control and other software that is not. In this column, I’m going to discuss how we can recognize these two categories, what happens when engineers on a project have different attitudes about intellectual control, some advice on when we probably should insist on it, and some ideas about how we achieve it.

[Read More]

IEEE Software - Architectural Hoisting

This column was published in IEEE Software, The Pragmatic Architect column, July-Aug 2014, Vol 31, number 4.

Abstract: Architectural hoisting is a design technique where the responsibility for an intentional design constraint (that is, a guiderail) is moved away from developer vigilance into code, with the goal of achieving a global property on the system.

[Read More]