“Would it help if we reduced the number of questions from fifteen to ten?”
That was the response when I asked what I had thought was a fairly ordinary question:
“What’s the algorithm?”
I had just joined a small marketing company that had decided it was actually a new media IT company. They had landed a project connected with Pedigree Chum and the Crufts Dog Show. Their big idea was to build a little interactive exhibit called Selectadog. Visitors would amble over to a stand, answer a series of questions about their lifestyle, and the software would recommend the perfect breed of dog for them.
They had the list of questions. They had a big list of dog breeds. They suggested I could probably lift some photographs of dogs from the internet.
What they did not have was the faintest idea how the answers to the questions should determine the dog.
When I asked for an algorithm, the company owner paused thoughtfully, blinked a couple of times, and then suggested that perhaps we should just ask fewer questions.
That was not quite the answer I had in mind.
I had taken the job in a hurry. I had been made redundant at the age of twenty-six and, in a mild panic, had accepted the first offer that came along. I handed in my notice on the fifth day. Some of their other requests were even stranger, and I decided that a tactical retreat was the wisest course of action.
But over the years I have come to appreciate that the Selectadog problem was not so unusual at all.
Software development work tends to sit somewhere on a spectrum.
At one extreme you have problems that are perfectly defined. Very early in my career I worked on IBM mainframe systems for a high-street bank, writing Assembler. Much of the work involved things like interest calculations and Y2K conversions. Those algorithms were specified to the last nibble: regulatory rules, financial formulae, rounding behaviour — everything precisely defined.
There was no room for creativity. The job was simply to implement the rules correctly, reliably, and in the house style.
At the opposite extreme you get something like Selectadog. The inputs are known — a set of questions about a user’s lifestyle. The output is known — a recommended dog breed. But the thing that connects them, the logic that turns the answers into recommendations, does not exist.
Nobody has decided how the dog is actually chosen.
“Ask people some questions and recommend the right dog.”
It sounds like a programming problem, but it isn’t. It’s a missing model. Someone has to decide what actually matters when choosing a dog. Energy level? Size? Shedding? Temperament? And how do those traits relate to answers about garden ownership, exercise habits, working hours, or children?
Once those rules exist, the software becomes relatively straightforward and deterministic. But defining those rules is the real intellectual work.
The work that I have most enjoyed during my career has lived somewhere between those two extremes. Not perfectly specified like mainframe banking algorithms, but not completely woolly and undefined like Selectadog either. There is a pleasant middle ground where product teams have a sense of what they want, but the precise rules of the system have not yet been worked out. Multidisciplinary teams can work together to tease out a design that meets the needs of the user, while balancing nonfunctional goals as appropriate to the business. It’s a joy to bring experience and judgement to those problems.
I have encountered this situation recently while integrating with an API for booking airport shuttle tickets. The API is impressively complicated and abstract. It exposes concepts of routes, terminals, fares, departure times, ticket types, passenger types — a small mechanical universe of options. Meanwhile the initial spec from the BA simply asked me to “call the API to book the tickets”. Which is a bit like asking someone to “just fly the plane”.
Somewhere between that sentence and the all-singing API lies an entire decision process that nobody has yet written down. Which departure should we choose? The earliest one? The cheapest one? What if several fares match? What if the bus doesn’t stop at the right terminal?
The API exposes the machinery. The spec describes the outcome. But the detailed thinking that connects them, in a way that provides an appropriate user experience, still needs to be invented.
In other words, nobody has yet decided which dog this system is supposed to choose. And that, I have come to realise, is actually the most interesting part of the job.
For most of the history of software development, writing the code was the bottleneck. Even once the rules of a system were understood, implementing them still required hours, days, possibly months of careful work. It was natural to think of programming primarily as the act of producing code.
But that assumption is crumbling. Tools like Copilot, Claude, and Codex are dissolving that bottleneck. Give them a well-defined problem and they are astonishing. They will happily generate classes, APIs, tests, and refactors faster than most humans can read them. The mechanical part of programming is becoming cheap.
I received a message recently from one of the best coders I’ve had the privilege to work with:
Can I ask… because I’m curious… are you using AI tools for generating code during development at work? I was interviewing somewhere on Friday and they seemed surprised I was manually coding. I didn’t even know that was unusual!
I am. I still review the outputs, tweak and refine them, and there’s still some back and forth. But it is so much faster, why wouldn’t I take advantage of agentic coding assistants?
For a long time the defining skill of our profession was the ability to produce working code. But if the machines can increasingly generate large chunks of it, then the emphasis for our role naturally shifts somewhere else.
Ask an AI to implement a workflow or an API and it will happily produce code. Ask it which shuttle bus ticket the user should be given, and suddenly the problem becomes murkier.
Because that decision does not live in the code. It lives in the model of the world that the code chooses to implement. And that model still has to be invented, and refined.
This increasingly feels like the real shape of the job. Product teams describe what they want in broad terms. Someone still has to translate those ideas into precise rules and constraints, the clear description that humans and machines can work from. The framing still needs judgement, domain understanding, technical expertise, and a fair amount of careful thinking.
So after almost thirty years in the industry, I am reaching a slightly unexpected conclusion. The job was never really writing the software. The job was always deciding, at various levels, how the system should behave — working out the rules that convert messy real-world intentions to the precise logic that machines can execute.
The job was always choosing the dog.
