Task Manager: Validated addTask and Filtered, Sorted printTasks With Child Tasks
Company: Rippling
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
Implement an in-memory task manager in Java with two operations, `addTask` and `printTasks`. In the reported version a task is a Java `record` with the fields below; for two of them the exact type was not recalled, and both possibilities are listed.
| Field | Type | Meaning |
| --- | --- | --- |
| `id` | `int` | The task's id |
| `description` | `String` | The text printed for the task |
| `dueDate` | `int` | The due date; `-1` means the task has no due date |
| `isPriorityTask` | `boolean` | Whether the task is a priority task |
| `createdDate` | `int` | The creation date |
| `assignee` | `String` (possibly `int`) | Who the task is assigned to; a task may have no assignee |
| `status` | `int` (possibly `boolean`) | Whether the task is done |
| `parentTaskId` | `int` | The id of the task's parent task, if it has one |
`printTasks` prints only the tasks that have no assignee **and** are not done, ordered by:
1. `dueDate` ascending, except that `-1` (no due date) comes after every real due date;
2. then priority tasks (`isPriorityTask == true`) before the others;
3. then `createdDate` ascending.
Each task prints on one line:
- a task without a parent: `{taskId}: {taskDescription}`
- a task with a parent: `{taskId}: {taskDescription}: {parentTaskId}: {parentTaskDescription}`
The interview provides one test case. After it passes, you are expected to add edge cases yourself and to assume that any input can be bad: `null` and empty values, duplicate tasks, and tasks that violate the statement, such as `id <= 0`, a description with leading or trailing spaces, `dueDate < -1`, `createdDate <= 0` (the statement never shows such a value, but it is a deliberate test point), or a parent task that was never added. Decide how each case is handled and explain your choice.
### Clarifying Questions
- What should `addTask` do with a task whose id already exists: reject it, overwrite the stored task, or ignore it? Not every version of the statement mentions duplicates; if yours does not, write your assumption as a code comment and move on.
- How is "no assignee" represented, and which `status` value means done?
- Which `parentTaskId` value means "no parent", and must a parent be added before its child?
- Should invalid input throw an exception, be skipped and reported, or be repaired, for example by trimming a description?
- What decides the order when the due date, the priority flag and the created date are all equal?
- Does `printTasks` write to standard output, return the lines, or both?
### Part 1 — Add, validate, filter, sort and print
Implement `addTask` and `printTasks` as described, including validation of every field and handling of duplicate tasks, then extend the provided test with your own edge cases.
```hint One place for bad input
Consider routing every check through a single validation method that `addTask` calls, so each rule and the behavior you chose for it are easy to state and to test.
```
```hint Encode the order once
Think about how to express the three ordering keys, including the special `-1` due date, in one reusable comparator instead of inline in the printing loop.
```
#### What This Part Should Cover
- A correct ordering: `-1` due dates last, priority before non-priority, then creation date, with a deterministic final tie-break
- The filter and both line formats exactly as specified
- A validation method with an explicit, consistent policy for every invalid input and for duplicates
- Edge-case tests beyond the provided one
### Part 2 — Print child tasks
Each task gains a `childTaskIds` list. `printTasks` keeps the same filter and order for the tasks it prints, and each printed task now also prints its child tasks, to which the same filter and ordering apply. The report does not give the exact output format for children, so propose one and confirm it.
```hint Reuse, don't rewrite
Think about which pieces of Part 1 (the filter, the comparator, the line format) can be applied unchanged to a task's children.
```
#### Clarifying Questions for this Part
- How are children shown: on indented lines under their parent, appended to the parent's line, or in another format?
- Do the children's own children print too, at every depth?
- Does a child task still appear in the main list as well as under its parent?
- What if a child id refers to a task that was never added, or a child's `parentTaskId` disagrees with its parent's `childTaskIds`?
#### What This Part Should Cover
- Children filtered and ordered with exactly the Part 1 filter and comparator
- Handling of missing child ids, inconsistent parent and child links, and cycles
- A clear, confirmed output format for nested tasks
### What a Strong Answer Covers
- Reading a long statement carefully but quickly, and turning every ambiguity into a stated assumption written as a code comment instead of a long discussion
- Clean modeling: an immutable task record, a map keyed by id, one reusable comparator and one validation method
- Exact output formatting and ordering, checked by tests
- Proactive edge-case tests covering `null`, empty, duplicate and invalid inputs
- Code shaped so that Part 2 adds children without rewriting Part 1
### Follow-up Questions
- Tasks can be marked done or reassigned after they are added. How would you support that with an immutable record, and what changes in printing?
- If `printTasks` were called far more often than `addTask`, how would you avoid sorting on every call?
- Some tasks can start only after others finish. How would you print an order in which every task comes after the tasks it depends on, and detect when no such order exists?
- How would you guarantee that `parentTaskId` and `childTaskIds` never disagree?
Overview: Implement an in-memory Java task manager whose addTask validates input and handles duplicates, and whose printTasks shows unassigned open tasks ordered by due date, priority and creation date with parent details, then prints child tasks under the same rules. Tests comparator design, input validation and proactive edge-case testing.
Read the full Rippling Software Engineer interview experience this question came from