Golden rules for task-tracking systems

This is the first in a series on software process.

In software development, keeping track of tasks—the things that need to be done—is second only to actual programming. But there is debate about precisely how to keep track of tasks. Task-tracking tools come in a variety of flavors.

I have used several systems on numerous projects and I developed an in-house system for my company way back in 2002. If you find yourself in a position to create or select a task tracker, I recommend considering the following golden rules for task-tracking systems.


A task tracker is for programmers. Its primary focus is giving relevant information about tasks to programmers and facilitating communication among the team about tasks. Put simply, the goal of a task tracker is to keep your programmers programming efficiently.

Analysis, reporting, and providing information to managers are ancillary functions and should be treated as such to avoid costly overhead. The value of ancillary functions must be weighed against the additional friction they contribute, with great deference to the primary focus of keeping programmers programming efficiently.


A task tracker exists to keep your programmers programming. Always be mindful of the ideal workflow for programmers, which is, in priority-descending order:

  1. Step 1: Program. Work on a programming task.
  2. Step 2: Track. Record progress on the task, find another task to work on, and then return to step 1.
  3. Step 3: Other stuff. Maybe read Hacker News.

A task tracker needs to keep the programmer in “Step 1: Program” as much as possible. Step 2 is a necessary evil to be minimized. Consider that each additional second your task tracker asks the programmer to wait for it to do some computation is another second you risk distraction before the programmer returns to the nirvana state of Step 1.

In other words, it is your task tracker's responsibility to prevent Step 2 from leaking programmers to Step 3. Return them to Step 1 as quickly as possible.


Keep everything as simple as possible in order to maximize programmer efficiency.

Use obvious terminology. I use the word “task” to refer to the universe of work items including planning, feature development, bug fixes, deployment efforts, changes, enhancements, research, and more.

Any work activity that meets a minimum threshold is a candidate for representing as a task. That threshold and the granularity of tasks is beyond the scope of these golden rules. The threshold may be a low bar, but it usually remains high enough to omit silly meta-tasks such as "Add necessary tasks to the tracker."

Some more examples of simple terminology:

  • Project: any group effort that has associated tasks.
  • Priority: the importance of a task.
  • Type: the type of a task (e.g., bug fix, feature).
  • Status: the current status of a task (e.g., in-progress, ready for QA, complete).

Ruthlessly prune task attributes/fields. The following is an idealized nearly-minimal task:

class Task { long id; String title; String description; Date creation; Date lastModification; Type type; // enum of task types Priority priority; // enum of priority levels Status status; // enum of status levels long assignedUser; // optional assignment to a specific programmer long reportedBy; // optional capture of the task's creator List<Attachment> attachments; List<Comment> comments; }

Fight against increasing the list of fields on tasks. Some things to keep in mind when considering additional fields:

  • If your programmers are asking for an additional field, it's probably fine to add it. They are asking for it because they think it will increase their productivity. Examples of fields programmers ask for are things like tags, related tasks, or build identifiers.
  • Make fields optional. Requiring data entry in task fields leads to untracked work. The more the act of creating and tracking tasks is seen as a nuisance, the greater the set of work that will be (perhaps unconsciously) untracked.
  • If possible, periodically review fields and remove any that are not providing sufficient utility versus their burden.

Single authoritative list of tasks

Perhaps the most important rule is this: a task tracker must provide a single authoritative list of tasks. The singular list can then be sorted and filtered in any fashion, but it must never be split or duplicated. A programmer should not need to hunt across multiple user interfaces to comprehend the total universe of tasks.

A task tracker aims to inform programmers about work that needs to be done as efficiently as possible. The most common question a programmer will have for a task tracker is:

What should I work on next?

The answer to this question needs to be immediate and as unambiguous as possible.

Render the singular list of tasks in priority-descending order and the programmer can immediately identify and consume an actionable task. Selecting a task is simple: aim for the highest priority while considering caveats such as capability, interest at the moment, responsibility areas, and so on.

The biggest complaint I have with many task trackers is the matter of ambiguous task priority. For example, a task tracker that provides a list of tickets, along with To-Do Items, User Stories, a Kanban board, and any number of additional lists, queues, or other things competing for programmer attention makes it extremely difficult to know what to do next. Is an urgent To-Do item more important than a high-priority User Story? That is unknown at worst and unclear at best. The ambiguity of priority is more annoying to programmers than you might imagine.

(Of course the general problem evidenced by many task trackers is a priority ambiguity of the underlying development process; but a measure of sanity can be achieved by selecting a task tracker that enforces a single authoritative task list. This can help keep your process in check.)

Corollary: Limit exports

While nearly all task trackers allow for task data to be exported, you are best served by limiting this to strictly read-only use-cases. Permitting team members to mutate tasks in a separate file or system leads inevitably to programmer confusion. Once split from the authoritative list, the exported data becomes a bit of a "split brain" which causes ambiguity. Programmers will rightfully wonder: "Are we working on the tasks in the tracker or the tasks in that Google spreadsheet you created?"

Don't maintain two or more authoritative lists, in any form, no matter how temporary.

Corollary: Singular priority metric

Avoid any scenario where the priority of tasks is ambiguous. The task tracker should always be able to present programmers with an unambiguous priority-descending sorted list of tasks.

Priority ambiguity can appear when multiple fields capture notions that are proximate to priority. If you find yourself considering the addition of fields with names such as "Severity," "Impact," or "Cost," be aware that adoption of these fields must be paired with additional project manager responsibility. The project manager incurs the burden of rendering the new proximate-priority fields into the tasks' actual "Priority" field.

Programmers should habitually sort by Priority and (more or less) ignore proximate-priority fields. Therefore, if the project manager believes a "High Severity" or "High Cost" task needs programmer attention, they must increase the Priority of that task rather than expect that a programmer will understand that High Severity implies High Priority.

Obvious canonical task identifier

Programmers need to be able to collaborate on tasks in many ways including by chat, email, and verbally. It is crucial that the task tracker provide an obvious canonical identifier for each task. This can be a simple number (e.g., 53910) or a string that bakes together a project code and a number (e.g., TPM-53910). Usually the identifier is what you see at the end of the URL used to edit the task in the tracker.

This seems so routine that you might be wondering why it needs to be stated as a golden rule.

At least two major systems that I've seen used for task tracking (Trello and Basecamp—yes, I've seen it used as a task tracker) appear to have been designed to expressly avoid easy reference to tasks by an identifier, as if following some crazy UX advice from the devil.

Hiding the identifier for tasks is a dark pattern in task trackers.

Your tracker won't fix unrelated dysfunction

Don't rely on a task tracker to resolve unrelated problems such as a dysfunctional team (e.g., programmers that don't communicate well with one another) or a dysfunctional process (e.g., irrational obsession with valueless metrics).

If you find yourself thinking it makes sense to fix a broken process or broken team by adding more fields to your tracker, or creating a "hit list" of tasks in a spreadsheet, or whatever half-baked tactic: stop and reevaluate. Dysfunction needs to be corrected at the root. Breaking the golden rules for task tracking above to fix unrelated dysfunction will suppress the efficiency of your well-functioning team members and is unlikely to actually resolve the dysfunction.
About this blog