Bugs, Tasks, and Tickets from First Principles

Why do we track tasks?

Bugs/defects are a kind of task but not the only kind. Most teams have a “bug tracker” that contains a lot more than bugs. Let's not let bugs dictate the system.

Bugs are an important kind of task.

Tasks can be related to software development artifacts: commits, versions, builds, releases.

Communication loosely implies publishing. Tracking doesn't, but may rely on the publishing of other facts.

Core Data

Tasks are only useful if they're actionable. To be actionable, they must be understood. Understanding requires communication and documentation.

See speciation, below.

Responsibility and Ownership

Regardless of whether your team operates with a top-down, command-oriented management structure or with a more self-directed and anarchistic process, for every task, there is notionally one person currently responsible for ensuring that the task is completed.

That relationship can change over time; how it does so is probably team-specific.

There may be other people involved in a task that are not responsible for a task, in a number of roles. Just because I developed the code for a feature does not mean I am necessarily responsible for the feature any more, but it might be useful to have a “developed by” list for the feature's task.

Ways of identifying people:

Task responsibility relationships reflect real-world responsibility, and help communicate it, but do not normally define it.

Workflow

“Workflow” describes both the implications of the states a task can be in and the implications of the transitions between states. Most task trackers are, at their core, workflow engines of varying sophistication.

Why:

States are implicitly time-bounded, and joined to their predecessor and successor states by transitions.

Task state is decoupled from the real world: the task in a tracker is not the work it describes.

Elemental states:

Most real-world workflows introduce some intermediate states that tie into process-related handoffs.

For software, I see these divisions, in various combinations, frequently:

None of these are universal.

Transitions show how a task moves from state to state.

States implicitly describe a belief or a desire about the future of the task, which is a human artifact and may be wrong or overly hopeful. Tasks can transition to “Completed” or “Abandoned” states when the work hasn't actually been completed or abandoned, or from “Completed” or “Abandoned” to an “Open” state to note that the work isn't as done as we thought it was. This is a feature and trackers that assume every transition is definitely true and final encourage ugly workarounds like duplicating tickets to reopen them.

Speciation

I mentioned above that bugs are a kind of task. The ways in which bugs are “different” is interesting:

Being able to support this kind of highly detailed speciation of task types without either bloating the tracker with extension points (JIRA) or shoehorning all features into every task type (Redmine) is hard, but necessary.

Supporting structure helps if it leads to more interesting or efficient ways of using tasks to drive and understand work.

Bugs are not the only “special” kind of task:

Other kinds are possible, and you've probably seen them in the wild.

Ideally, speciation happens to support widespread specialized needs. Bug repro is a good example; every task whose goal is to fix a defect should include a clear understanding of the defect, both to allow it to be fixed and to allow it to be tested. Adding specialized data for bugs supports that by encouraging clearer, more structured descriptions of the defect (with implicit “fix this” as the task).

Implementation notes

If we reduce task tracking to “record changes to fields and record discussion comments, on a per task basis,” we can describe the current state of a ticket using the “most recent” values of each field and the aggregate of all recorded comments. This can be done ~2 ways:

  1. “Centralized” tracking, where each task has a single, total order of changes. Changes are mediated through a centralized service.
  2. “Decentralized” tracking, where each task has only a partial order over the history of changes. Changes are mediated by sharing sets of changes, and by appending “reconciliation” changes to resolve cases where two incomparable changes modify the same field/s. The most obvious partial order is a digraph.

Centralized tracking is a well-solved problem. Decentralized tracking so far seems to rely heavily on DSCM tools (Git, Mercurial, Fossil) for resolving conflicts.

The “work offline” aspect of a distributed tracker is less interesting in as much as task tracking is a communications tool. Certain kinds of changes should be published and communicated as early as possible so as to avoid misunderstandings or duplicated work.

Being able to separate the mechanism of how changes to tasks are recorded from the policy of which library of tasks is “canonical” is potentially useful as an editorial tool and for progressive publication to wider audiences as work progresses.

Issue tracking is considerably more amenable to append-only implementations than SCM is, even if you dislike history-editing SCM workflows. This suggests that Git is a poor choice of issue-tracking storage backends...