The development process can often be opaque, and developers sometimes find it easy to hide behind complex requirements that take an indeterminate time to finish. This is a bad thing.
The reason for requiring every issue to be user driven comes down to the meaning of an issue. For us an issue is a thing that changes the system for a human being. If the issue doesn’t have an impact on a user it’s not a useful issue.
(To be clear upfront, our definition of the word issue is not quite pure agile. We mingle stories, issues and tasks into a something that lies somewhere in the middle, but the discussion below is applicable to traditional stories and issues as well.)
Taking this position allows us to do a few things. Firstly we can always define what ‘done’ means for an issue, namely it’s when the human being confirms the change they expected has happened.
Secondly it means we can fully define the issue in human language without worrying about the backend details. There might be complexities in the implementation, but if the end result is the button goes green, well, that’s the reason for the issue. I like to point out that most clients don’t care if the solution involves penguins pushing icebergs around so long as the result is the same. In the same vein, we’re not creating issues for the purposes of writing code, we’re creating issues to solve a human problem.
We’re not saying that there’s no reason to consider how to design a database for example, just that the database design isn’t the reason for the issue. The database, the api, the inter-system protocol layer, they’ll all come along for the ride, but they are not the reason the issue exists.
While this approach works well most of the time, the reality that we’re often confronted with is, what to do about those inevitable issues that ‘obviously have no user interface’. Some of these objections are easy to dismiss if you include Excel dumps and pdfs as output. They really are output so that’s not cheating.
It’s a bit harder when the thing to do is, say, copy today’s database dump from the production server to the backup server. Surely there’s no user impact there? But of course there is, at the extreme the user experience we’re looking for is the ability to crash the production server and confirm the devs can bring it up again without losing any data.
Demonstrating that is a bit extreme for a single issue, especially since we want sub-4 hours issues as a rule. The challenge therefore is to identify a user change in the simplest possible way so that the core of the issue is still to do the heavy dev work required, while also making it visible.
Often a log on an admin page is enough. So maybe we’ll add a table with a row for every time the dump was copied, with a timestamp for good measure. In that way we’ve solved the visibility constraint, and additionally got the benefit of logging, ease of testing and ongoing confirmation that the backup is working.
This example solution only works if the effort to add the table is an insignificant part of the issue, we don’t want to pad issues and turn them into nightmares of development, so it depends on context. If there isn’t an admin page already, perhaps the solution is an email to a super user, that’s still a user interface and if there’s already an email server as part of the solution then that’s often pretty easy.
Or perhaps the solution is simply to display the output to the screen when you’re running the program. But be careful, the output must be visible to a non technical user, otherwise you’ve lost the power of this constraint. The idea only works if a non-developer can confirm that the issue works, without access to development tools.
A much harder example is so-called technical debt. This issue is something thrown into a project to account for a refactoring that’s required, or an upgrade to a new package, or just fixing poor code by the last guy who was fired. This can be very problematic to solve. At one level, these issues are often simply too big to be acceptable in a sprint. They are highly unlikely to be estimatable, will often destabilise the system, and managers hate them. There’s no one-word answer here, sometimes you simply have to upgrade and the only human output you can say is that “the system still works and is slightly faster”.
But even here, we suggest you make the effort to find a way to make it smaller and tractable. Perhaps you’ll suspend the 4-hour-per-issue requirement just this once. Perhaps you can upgrade just one package at a time. Perhaps you can wrap the bad code in a new function and put up with it for now, with instructions to all devs to make one fixing tweak every time they see the code (continuous refactoring). It depends on the team and how bad the problem is.
Even in the worst case, don’t abandon the reason for this constraint though. If the developer can’t show output after each issue, and if issues can’t be small enough to be finished in one day, you’ve lost something very valuable. And your project might enter development hell, never to emerge.