Skip to main content

Requirements for the Task Manager

Editorial

Functional Requirements

Let's define exactly what our Task Management System must do. Each requirement is specific enough to drive a class, method, or relationship in our design.

Task Lifecycle:

  1. R1 — Create a Task: A user can create a new task with a title (required), description (optional), priority (LOW, MEDIUM, HIGH, URGENT), and an optional due date. Every task receives a unique identifier on creation. The initial status is always TODO.

  2. R2 — Update a Task: A user can modify a task's title, description, priority, or due date after creation. Each update is recorded so it can be undone.

  3. R3 — Delete a Task: A user can delete a task from a task list. Deleted tasks are removed permanently. The deletion itself is undoable (the task can be restored).

  4. R4 — Task Status Transitions: A task's status can transition through the following states: TODO → IN_PROGRESS → DONE. Additionally, any state can transition to CANCELLED. Moving backward (e.g., DONE → IN_PROGRESS) is allowed for reopening tasks. Invalid transitions (e.g., TODO → DONE directly) are rejected.

Assignment and Organization:

  1. R5 — Assign a Task: A task can be assigned to exactly one user at a time. Reassigning a task to a different user replaces the current assignee. Unassigned tasks are permitted.

  2. R6 — Task Lists: Tasks are organized into task lists (think Trello boards or Jira projects). A task belongs to exactly one task list. A task list has a name and can contain zero or more tasks.

  3. R7 — Search and Filter: Users can retrieve tasks filtered by: status, priority, assignee, or due date range. Multiple filters can be combined (e.g., "all HIGH priority tasks assigned to Alice that are IN_PROGRESS").

Notifications:

  1. R8 — Watch a Task: Users can subscribe to (watch) a task. A user who watches a task receives notifications when the task's status, assignee, priority, or due date changes.

  2. R9 — Notification on Change: When a watched task is modified, all watchers are notified with the change details (what field changed, old value, new value). The assignee is implicitly a watcher.

Undo/Redo:

  1. R10 — Undo: The system supports undoing the most recent task operation (create, update, delete, status change, assignment). Undo reverses the operation — restoring the previous state.

  2. R11 — Redo: After an undo, the user can redo to reapply the undone operation. If a new operation is performed after an undo, the redo history is cleared.

User Management:

  1. R12 — User Identification: Each user has a unique ID and a name. Users can create tasks, be assigned tasks, and watch tasks.

Non-Functional Requirements

Beyond what the system does, here's how it should behave:

  1. Extensibility (Open/Closed Principle): Adding a new task status (e.g., BLOCKED, IN_REVIEW) should not require modifying existing classes that handle status transitions. Similarly, adding new notification channels (e.g., email, Slack webhook) should not require changes to the task update logic.

  2. Testability: Each component — task CRUD, notification dispatch, undo/redo — should be testable in isolation. The Observer and Command patterns help here by decoupling responsibilities.

  3. Single Responsibility: The class that manages task storage should not also handle notifications. The class that executes commands should not also manage the undo/redo stack. Each class has one reason to change.

  4. Undo Safety: The undo/redo mechanism must be consistent — undoing a "create" must fully remove the task, undoing a "delete" must fully restore it, and undoing a field update must restore the exact previous value.

Scope Clarification

In Scope:

  • Task CRUD operations (create, read, update, delete)
  • Task status transitions with validation
  • Task assignment to users
  • Task lists as organizational containers
  • Observer-based notification system for task watchers
  • Command-based undo/redo for all task mutations
  • Filtering tasks by status, priority, assignee, and due date
  • User identification (ID + name)

Out of Scope:

  • Persistence — no database layer; all data lives in memory. In a real system, you'd add a repository layer.
  • Authentication/Authorization — we assume any user can perform any operation. A real system would enforce role-based access (admin, member, viewer).
  • REST API layer — no HTTP endpoints. We design the domain model that an API layer would call.
  • Real-time sync — no WebSocket notifications. Our Observer delivers in-memory callbacks.
  • Sub-tasks and dependencies — tasks are standalone. Adding parent-child relationships is a natural extension but not core.
  • Comments and attachments — these are common features in real task managers but add complexity without introducing new design patterns.
  • Recurring tasks and templates — out of scope for this design.

Requirements → Design Mapping

Here's a preview of how each requirement will drive our class design:

RequirementDesign Element
R1 (Create Task)Task class with id, title, description, priority, dueDate, status
R2 (Update Task)UpdateTaskCommand encapsulating field-level changes
R3 (Delete Task)DeleteTaskCommand with undo restoring the task
R4 (Status Transitions)TaskStatus enum + validation logic in Task.transition()
R5 (Assign Task)AssignTaskCommand + assignee field on Task
R6 (Task Lists)TaskList class composing multiple Task objects
R7 (Filter)Filter methods on TaskManager accepting status, priority, assignee, date criteria
R8 (Watch)Observer pattern — Task maintains list of TaskObserver subscribers
R9 (Notify)TaskObserver interface with onTaskChanged() callback
R10 (Undo)Command pattern — CommandHistory managing an undo stack
R11 (Redo)CommandHistory maintaining a redo stack cleared on new commands
R12 (Users)User class with id and name

Every class in our design traces back to at least one requirement. If a class can't be justified by a requirement, it shouldn't exist.

Interview Tip

In a real LLD interview, spend 3-5 minutes clarifying requirements before jumping into design. For a Task Management System, smart clarifying questions include:

  • "Should tasks support sub-tasks or dependencies?" — This dramatically increases complexity. Clarify early.
  • "Is undo per-user or global?" — We'll design it as global (one shared history), but per-user undo is a valid extension.
  • "Can a task exist outside a task list?" — We'll require every task to belong to exactly one list.
  • "How many watchers per task do we expect?" — This helps determine if a simple list suffices or if we need a more scalable structure.
  • "Are status transitions strictly linear, or can tasks move backward?" — Our design allows reopening (DONE → IN_PROGRESS) but rejects skipping (TODO → DONE).

These questions show the interviewer that you think about edge cases and scope boundaries — not just the happy path.