diff --git a/use-cases/task-manager/javascript/documentation.md b/use-cases/task-manager/javascript/documentation.md new file mode 100644 index 00000000..1e7c51af --- /dev/null +++ b/use-cases/task-manager/javascript/documentation.md @@ -0,0 +1,146 @@ +# Exercise 1 Code Understanding + +## Language Used +The code I have chosen is **JavaScript**. + +# Code Breakdown + +## Codebase + +There are 4 javascript files it appears. +There seems to be an attempt at a backend by using module.export and the require key word and file paths but no official frameworks. + +## Initial Understanding +### Organization +- It appears app.js is the main file. +- cli.js seems to convert the project into a usable command line interface by creating a program constant and using the commander library to create a command line interface. +- models.js seems to be handeling the task management of the project +- storage.js seems to be running where and how the project data is stored. It can also edit the stored data. + +### Frameworks and technologies +- module exports +- CLI tools/commander library +- Task manager class +- Engine uuidv4 +- File pathing + +### Main Components +- CLI Tools +- File pathing + +## Project Structure +### Using Prompt +*** My Prompt *** +I'm a junior developer who just joined this project. I've read the README but still need help understanding the project structure and technology stack +Here's my current understanding of the project: + +## Codebase + +There are 4 javascript files it appears. +There seems to be an attempt at a backend by using module.export and the require key word and file paths but no official frameworks. + +## Initial Understanding +### Organization +- It appears app.js is the main file. +- cli.js seems to convert the project into a usable command line interface by creating a program constant and using the commander library to create a command line interface. +- models.js seems to be handeling the task management of the project +- storage.js seems to be running where and how the project data is stored. It can also edit the stored data. + +### Frameworks and technologies +- module exports +- CLI tools/commander library +- Task manager class +- Engine uuidv4 +- File pathing + +### Main Components +- CLI Tools +- File pathing +Project structure +task-manager + --Java + --Javascript + --app.js + --cli.js + --models.js + --storage.js + --python +We are only focussing on the JavaScript folder +Configuration Files: +None +Could you: +1. Validate my understanding and correct any misconceptions +2. Identify additional key technologies, frameworks, and libraries used +3. Explain what each main folder likely contains and its purpose +4. Point out where the application entry points are located +5. Suggest 3-5 specific questions I should ask my team to deepen my understanding +After your explanation, could you suggest a small exploration exercise I could do to verify my understanding of the project structure? + +*** Claude Response *** +1. Validating Your Understanding +Your instincts are largely correct, with a few refinements: +What you got right: + +app.js as the main entry point is a standard Node.js convention — good call. +cli.js using Commander to expose a CLI is accurate. Commander is a well-established library for parsing command-line arguments and defining commands/flags. +storage.js handling data persistence (read/write) is a sensible separation of concerns. +models.js containing a Task management class is a classic MVC-style "model" layer. + +Misconceptions to correct: + +"An attempt at a backend" — module.exports and require are not signs of an incomplete or attempted backend. They are simply Node.js's built-in CommonJS module system, the standard way to split code across files in Node.js. This is intentional and complete, not a workaround. +"No official frameworks" — this is likely a deliberate architectural choice. Many CLI tools are built as lightweight Node.js apps without Express or similar, because they don't serve HTTP traffic. The absence of a framework isn't a gap; it's appropriate for the tool's purpose. +"Engine uuidv4" — UUIDv4 is not an engine. It's a small utility library for generating universally unique IDs (e.g. giving each task a unique identifier like f47ac10b-58cc...). Think of it as a helper, not a runtime. + + +2. Key Technologies & Libraries +Based on your description, here's the fuller picture: +TechnologyRoleNode.jsThe JavaScript runtime — what actually executes the codeCommonJS (require/module.exports)Node's module system for splitting code across filesCommander.jsParses CLI arguments, defines commands and flagsuuid / uuidv4Generates unique IDs for each taskNode fs moduleAlmost certainly used in storage.js for reading/writing files to diskJSONLikely the storage format (a flat .json file acting as a simple database) + +3. What Each File Likely Does +task-manager/ +└── Javascript/ + ├── app.js → Wires everything together. Imports the CLI and kicks off execution. + ├── cli.js → Defines user-facing commands (e.g. `add`, `list`, `delete`). + │ Uses Commander to parse what the user types in the terminal. + ├── models.js → The Task class/object. Defines what a task looks like (id, title, + │ status, etc.) and methods to operate on tasks. + └── storage.js → Reads from and writes to a file on disk. Handles all persistence + so the other files don't need to know *how* data is saved. +The Java and Python folders likely contain parallel implementations of the same task manager — a common pattern for learning projects or polyglot codebases demonstrating the same app in multiple languages. + +4. Entry Points +There are likely two entry points depending on how the app is used: + +app.js — the primary Node.js entry point, probably run via node app.js or referenced in a package.json "main" field. +cli.js — may also be executable directly (e.g. node cli.js add "Buy milk"), or it's imported by app.js which delegates to it immediately. + +Check for a package.json — if it exists, the "bin" or "main" field will tell you the definitive entry point, and "scripts" will show you how the team actually runs it. + +5. Questions to Ask Your Team + +"Is there a package.json, and what does the scripts section look like?" — This reveals how the app is built, run, and tested, and whether there are dependencies you haven't seen yet. +"Where is task data actually stored — a local JSON file, or something else?" — Understanding the storage target clarifies storage.js's full role. +"Is this CLI tool meant to be installed globally (npm install -g) or run locally?" — This affects how users interact with it and how Commander is configured. +"Are the Java and Python folders feature-equivalent to the JavaScript version, or are they experiments/stubs?" — Knowing this tells you whether cross-language consistency matters. +"Are there any plans to add tests?" — Junior-friendly question that reveals team practices and gives you a contribution opportunity. + + +Exploration Exercise +Try this structured trace-through — no code changes, just reading: + +Start at app.js — identify every require() call. Draw a simple arrow diagram of what it imports. +Open cli.js — find each .command() call in Commander. List the commands the app exposes (e.g. add, list, complete). +Open models.js — find the class definition. List its properties (what fields does a Task have?) and its methods. +Open storage.js — find where it reads and writes. What filename or path does it use? What format is the data? +Try running it — if Node.js is installed, run node app.js or node cli.js --help and see if the Commander help output matches the commands you found in step 2. + +## Findings +### Misconceptions to correct: +1. "An attempt at a backend" — module.exports and require are not signs of an incomplete or attempted backend. They are simply Node.js's built-in CommonJS module system, the standard way to split code across files in Node.js. This is intentional and complete, not a workaround. +2. Engine uuidv4" — UUIDv4 is not an engine. It's a small utility library for generating universally unique IDs (e.g. giving each task a unique identifier like f47ac10b-58cc...). +### Final Resault +1. My understanding of the project structure is mostly correct, with some refinements regarding the use of CommonJS modules and the role of uuidv4. +2. Key technologies include Node.js, CommonJS modules, Commander.js for CLI parsing, uuid +3. Each file has a clear purpose: app.js is the main entry point, cli.js defines the CLI commands, models.js defines the Task class, and storage.js handles data persistence. +4. The main entry point is likely app.js, but cli.js may also be directly executable \ No newline at end of file diff --git a/use-cases/task-manager/javascript/domainModel.md b/use-cases/task-manager/javascript/domainModel.md new file mode 100644 index 00000000..be080f6c --- /dev/null +++ b/use-cases/task-manager/javascript/domainModel.md @@ -0,0 +1,190 @@ +# Exercise 3 +# Domain Model +## Extract domain model from codebase +### Core classes +- TaskStorage +- TaskManager +- TaskPriority (enum for task priority levels) +- TaskStatus (enum for task status) +- Task class + + +## Initial Understanding +### Simple Diagram +```mermaid +classDiagram + TaskStorage <|-- TaskManager + TaskManager o-- Task + Task : +id + Task : +title + Task : +description + Task : +priority + Task : +status + + flowchart LR + A[Task Class] --> B[TaskManager] + B --> C[TaskStorage] + C --> D(TaskPriority) + D --> E(TaskStatus) +``` +1. The main Class A is the starting point +2. Class A leads to B which is the TaskManager class that handles the logic of managing tasks +3. TaskManager interacts with C (TaskStorage) which is responsible for data persistence +4. Task C interacts with D and E which are enums for TaskPriority and TaskStatus respectively, defining the possible values for these properties in a task. + +## Prompts +### Prompt Used +I'd like you to act as a senior developer who deeply understands our codebase's domain model. I'm a junior developer trying to make sense of the business logic and domain concepts in this application +Here's what I've found in the codebase: +### Core classes +- TaskStorage +- TaskManager +- TaskPriority (enum for task priority levels) +- TaskStatus (enum for task status) +- Task class +### Simple Diagram +```mermaid +classDiagram + TaskStorage <|-- TaskManager + TaskManager o-- Task + Task : +id + Task : +title + Task : +description + Task : +priority + Task : +status + + flowchart LR + A[Task Class] --> B[TaskManager] + B --> C[TaskStorage] + C --> D(TaskPriority) + D --> E(TaskStatus) +``` +1. The main Class A is the starting point +2. Class A leads to B which is the TaskManager class that handles the logic of managing tasks +3. TaskManager interacts with C (TaskStorage) which is responsible for data persistence +4. Task C interacts with D and E which are enums for TaskPriority and TaskStatus respectively, defining the possible values for these properties in a task. +Could you, as a senior developer: +1. Validate my current understanding, correcting any misconceptions +2. Help me recognize the core domain concepts represented in this code +3. Explain the relationships between these entities in business terms, not just technical relationships +4. Clarify any domain-specific terminology or patterns I might be missing +5. Help me connect these models to actual user-facing features or business processes + +Then, please ask me 3-5 questions that would test my understanding of this domain model. These should be questions that make me think about the business logic, not just the code syntax. + +Finally, suggest a simple diagram I could sketch to visualize these relationships that would help solidify my understanding. + +### Prompt Response +1. Validation & Corrections ✅ / ⚠️ +What You Got Right: + +✅ Task is the core entity +✅ TaskManager orchestrates business logic +✅ TaskStorage handles persistence +✅ TaskPriority and TaskStatus are domain constraints +Critical Misconceptions to Fix: + +⚠️ Relationship Direction: Your diagram shows TaskStorage <|-- TaskManager (inheritance with TaskStorage being the parent). This is backwards. + +Reality: TaskManager depends on TaskStorage (composition, not inheritance) +Better notation: TaskManager --> TaskStorage (TaskManager uses TaskStorage) +Why it matters: This is about dependency flow, not class hierarchies. TaskManager is the high-level layer that delegates to TaskStorage. +⚠️ Missing Domain Concepts: You're missing critical attributes that represent business requirements: + +tags - How users organize/categorize tasks +dueDate, createdAt, updatedAt, completedAt - Temporal tracking (when things happen) +isOverdue() - Business logic (a task is "overdue" when it's past due date AND not done) +markAsDone() - Explicit state transition with side effects (sets completedAt automatically) +2. Core Domain Concepts (Business Language) +Let me translate the code into real business/product thinking: + +Code Concept Business Concept Why It Matters +Task A unit of work Everything revolves around this—it's what users care about +Priority (1-4) Urgency signal Helps teams decide what to tackle first +Status (TODO→IN_PROGRESS→REVIEW→DONE) Workflow state Models the journey of work through a team's process +Tags Flexible categorization Users can organize by project, team, feature, bug type, etc. +dueDate Deadline Creates accountability and urgency +isOverdue() Business rule A task is only "overdue" if it has a deadline AND hasn't been completed—this is critical logic +TaskManager Task coordinator The "brains" of the system—validates input, applies rules +TaskStorage Record keeper Like a filing cabinet—doesn't make decisions, just stores/retrieves +3. Relationships in Business Terms +Real example from the code: + +This shows layered architecture: + +Presentation Layer (cli.js): "What can the user do?" +Business Logic (app.js): "What are the rules?" +Data Layer (storage.js): "How do we remember?" +4. Domain-Specific Patterns You Should Know +Pattern 1: Value Objects (TaskPriority, TaskStatus) + +Pattern 2: Domain Logic Living in the Entity + +Pattern 3: State Transitions + +Pattern 4: Lazy vs. Active Properties + +5. Connecting to User-Facing Features +Here's how the domain model enables real features: + +User Goal Feature Domain Concepts Used +"Show me what to do today" list with filters Task.status, Task.dueDate +"I'm working on this" status in_progress TaskStatus enum, Task.update() +"This is urgent" priority 4 TaskPriority enum, Task.priority +"Mark it done when complete" status done Task.markAsDone(), Task.completedAt +"Show stats" stats TaskStorage aggregations (getAllTasks, getTasksByStatus) +"Which tasks are late?" list --overdue Task.isOverdue() business logic + +📊 Improved Domain Model Diagram +Here's a better visualization (corrects your relationship directions): + +Key differences from your diagram: + +TaskManager --> TaskStorage (dependency arrow, not inheritance) +Added temporal tracking (createdAt, updatedAt, completedAt) +Added tags and methods that represent business logic +TaskStatus and TaskPriority are shown as enumerations +Added method signatures so you see what each layer is responsible for +💡 Mental Model to Carry Forward +Think of it like a restaurant kitchen: + +Task = A plate that needs to be prepared (the product) +TaskManager = Head chef (makes decisions, ensures quality, follows recipes) +TaskStorage = Pantry (remembers ingredients, keeps organized records) +TaskStatus = Stage of the order (ordered → cooking → plating → served) +Priority = How urgently the order should be cooked +Understanding these business concepts makes it much easier to extend the system—you'll know where logic belongs and what constraints you need to maintain. + +### Prompt Questions +Q1: The "Overdue" Concept + +A task with dueDate = May 20 and status = DONE (completed on May 18). Is it overdue? Check the isOverdue() method in the code. Why does the business logic check this.status !== TaskStatus.DONE? + +Q2: Tags Design + +Why do you think tags are stored as an array tags: [] rather than a single string? What business scenarios would multiple tags enable? + +Q3: When Does completedAt Get Set? + +In the code, completedAt only gets set when markAsDone() is called. What happens if someone calls updateTaskStatus(taskId, TaskStatus.DONE) directly instead? Is this a bug or intentional? (Hint: look at the code in app.js) + +Q4: Data Flow for "Show Me Overdue Tasks" + +If a user runs list --overdue, trace the path through all three layers. Where does each layer add value? What would break if you removed TaskManager and called TaskStorage directly from CLI? + +Q5: Statistics Aggregation + +The getStatistics() method in TaskManager counts tasks by status and priority. Why is this logic in TaskManager rather than in TaskStorage? What business decisions does this enable at the management level? + +## Testing Knowledge +### Questions +**Q1** +No it is not overdue, the completed date is before due date and status is marked as done. The isOverdue() method checks if the status is not DONE because a task that is already completed cannot be overdue, regardless of its due date. +**Q2** +Tags are stored in a array to allow for multiple tags to be associated with a single task. This enables users to categorize and organize tasks in more flexible ways, such as by project, team, feature, or bug type. +**Q3** +This is likely intentional. The markAsDone() method not only sets the status to DONE but also records the completedAt timestamp. If someone calls updateTaskStatus(taskId, TaskStatus.DONE) directly, it would change the status but would not set the completedAt timestamp, which could lead to incomplete data about when tasks were actually completed. +**Q4** +When a user runs list --overdue, the CLI layer (cli.js) would parse the command and recognize the --overdue flag. It would then call a method in TaskManager (app.js) that retrieves all tasks from TaskStorage and applies the isOverdue() logic to filter out only those tasks that are overdue. If you removed TaskManager and called TaskStorage directly from CLI, you would lose the business logic encapsulated in TaskManager, such as filtering for overdue tasks, and you would have to implement that logic in the CLI layer, which is not ideal for separation of concerns. +**Q5** +The getStatistics() method is in TaskManager rather than TaskStorage because it involves business logic that aggregates and interprets the raw data of tasks. TaskStorage's responsibility is to store and retrieve data, while TaskManager's role is to apply business rules and provide meaningful insights. By keeping this logic in TaskManager, it allows for more complex calculations and decision-making based on the task data, which can inform management decisions about resource allocation, project progress, and areas that may need attention. \ No newline at end of file diff --git a/use-cases/task-manager/javascript/finalDiscussion.md b/use-cases/task-manager/javascript/finalDiscussion.md new file mode 100644 index 00000000..0c959968 --- /dev/null +++ b/use-cases/task-manager/javascript/finalDiscussion.md @@ -0,0 +1,11 @@ +# Final Discussion +## Approach to understanding codebase +I found it quite fun to read through a code base and gaining a my own perspective on what it is about adn the using the prompts I leant to see what I missed and what I got tight +## Challenges +My main problem was running out of prompts as my chatbot had limited propmts. I created a GitHub with the email I was given for the course so I had a fresh account for prompts +## Most useful prompts +Prompt 1 was the most helpful as I could properly understand the logic of the project +## For future +I would use the prompt to identify what the local imported libraries are for and what they do as I had a hard time understanding the commander library and how it worked with the cli.js file. +## Additional tools +I would use a code editor with better search capabilities and a better terminal to run the project and test my changes. I also would have used a better chatbot with more prompts to ask about the project and my changes. \ No newline at end of file diff --git a/use-cases/task-manager/javascript/newFeature.md b/use-cases/task-manager/javascript/newFeature.md new file mode 100644 index 00000000..d9b446e8 --- /dev/null +++ b/use-cases/task-manager/javascript/newFeature.md @@ -0,0 +1,118 @@ +# Exercise 2 +Add task: Export to CSV +## Initial Search +No similar feature was found to convert a file to export + +## Hypothesis +I think the best place to use this feature would be in cli.js as it deals with the terminal mostly so it easily accessable to this applications and future implements. The terminal also has easy access to fiels so the conversion to csv would be easier to implement in this file. + +**no files need adjustment** + +### Search Terms +- "export to csv" +- "convert to csv" +- "exports" +- "csv" + +## Feature Location Prompt + +### Prompt Used +I need to work on adding a task: Convert to CSV in this codebase, but I'm not sure where the code for this feature lives. + +My approach so far: +- I've searched for keywords like "export to csv", "convert to csv", "exports", "csv" +- I looked in cli.js which seemed relevant +Can you help me: +1. Evaluate my search approach and suggest improvements +2. Identify which files and directories most likely contain the implementation for this feature +3. Suggest specific search terms or patterns that would be more effective +4. Explain what parts of the feature might be located in different areas of the codebase +5. Recommend a step-by-step investigation process to understand the complete feature flow + +Also, what questions could I ask myself as I'm exploring the code to ensure I'm on the right track? What specific patterns should I look for to confirm I've found all the relevant parts? + +After your guidance, could you give me a small challenge to test my understanding of how to navigate this feature's code? + +### Prompt Response +Comprehensive Navigation Guide for the CSV Feature +1. Evaluation of Your Search Approach ✓ +What You Did Well: + +Searched for direct keywords ("export to csv", "convert to csv") +Looked at cli.js (correct instinct—UI layer often reveals exposed features) +What Could Be Improved: + +Your search was feature-focused rather than architecture-focused—CSV export doesn't exist yet +Better approach: First understand the code structure, then search strategically +You correctly hypothesized cli.js but didn't yet map where the CSV conversion logic belongs +2. Files & Directories Most Likely to Contain CSV Logic +File Role Expected Changes +cli.js Command-line interface Add export or export-csv command +storage.js Persistence/file I/O Add exportToCSV() method (follows existing pattern) +app.js Business logic Optional: add exportTasks() method +models.js Data definitions No changes needed (already has Task structure) +3. Better Search Terms & Patterns +Instead of searching for "csv", try these sequences: + +4. How the Feature Flows Across the Codebase +5. Step-by-Step Investigation Process +Phase 1: Understand Data Structure + +Read models.js → What fields does a Task have? +Read storage.js → How are tasks stored/retrieved? (Look for getAllTasks()) +Trace: Where does task data originate and how is it accessed? +Phase 2: Identify Integration Points +4. Read cli.js → How are existing commands structured? (Look for program.command() patterns) +5. Compare: What do list, create, delete commands do? +6. Pattern Match: Find similar file-writing operations if any exist + +Phase 3: Locate Persistence Patterns +7. In storage.js, find the save() method → This is the model for CSV export +8. Question: Does save() use fs.writeFileSync()? Yes → Use same approach + +Phase 4: Determine Ownership +9. Is CSV logic belongs in storage.js (file I/O) or app.js (business logic)? +10. Check: Does app.js expose an getAllTasks() or similar public method? + +6. Questions to Ask While Exploring +Ask yourself these during code exploration: + +"Who calls this function?" → Trace backwards to see dependencies +"What data does this return?" → Understand the shape of data flowing through +"Where is file I/O happening?" → Look for fs. operations +"What's the pattern for similar features?" → Compare with list, stats, delete commands +"Which layer handles each responsibility?" → CLI? Business Logic? Storage? +"Is there a public API I should use?" → Via TaskManager or TaskStorage? +"What error cases exist?" → File permissions, invalid paths? +7. Patterns to Confirm You've Found Everything +✓ You've found it all when you can answer: + +Data Source: "I can get all tasks via this.storage.getAllTasks()" +Transformation: "I can convert task objects to CSV using headers + rows" +Output: "I can write to file using fs.writeFileSync() like the save() method does" +Integration: "I can add a new CLI command in cli.js like the stats command" +End-to-End: "User runs export-tasks --output file.csv → triggers handler → converts tasks → writes file" +8. Your Challenge 🎯 +Task: Without looking at any code, answer these: + +Data Flow: Where would you retrieve the task data for CSV export—from TaskStorage.getAllTasks() or from TaskManager.listTasks()? Why? +File Writing: Which method in storage.js shows you the exact pattern for writing files? Find it and identify the 2-3 lines you'd need to adapt. +CLI Integration: In cli.js, find one existing command and describe what happens in its .action() callback. +Ownership: Should the CSV formatting logic live in storage.js or a new separate file like formatters.js? Justify your answer. +Completeness Check: What would need to change in app.js to support taskManager.exportToCSV(filename)? +Try these now: Read just storage.js carefully and answer questions 1-2. Then read just one command in cli.js and answer question 3. Post your answers and I'll validate your understanding! + +## Findings +### Where to implement the feature +1. CLI Layer (cli.js) — Add a new command (e.g. export-tasks) that users can run from the terminal. +2. Storage Layer (storage.js) — Implement the actual logic to convert tasks to CSV format and write to a file. This keeps file I/O concerns separate from business logic. +3. Optional: Business Logic Layer (app.js) — If you want to keep CLI thin, you could add an exportTasks() method here that orchestrates the retrieval and formatting, but it's not strictly necessary. +### Related components to be affected +- cli.js — for the new command and its handler +- storage.js — for the CSV conversion and file writing logic +### Plan to implement export feature +1. In cli.js, define a new command (e.g. `export-tasks`) using Commander. +2. In the command's action handler, call a new method in storage.js (e.g. `exportToCSV(filename)`) that you will implement. +3. In storage.js, implement `exportToCSV(filename)`: +4. Retrieve all tasks (e.g. via `getAllTasks()`) +5. Convert tasks to CSV format (create headers, iterate over tasks to create rows) diff --git a/use-cases/task-manager/javascript/practical.md b/use-cases/task-manager/javascript/practical.md new file mode 100644 index 00000000..7ed1c70c --- /dev/null +++ b/use-cases/task-manager/javascript/practical.md @@ -0,0 +1,289 @@ +# Exercise 4: Practical Implementation Planning +## Scenario: Automatic Abandoned Task Rule + +**Business Rule:** "Tasks that are overdue for more than 7 days should be automatically marked as abandoned unless they are marked as high priority." + +--- + +## Planning + +### 1. Files That Need Modification + +#### **models.js** (HIGH PRIORITY) +- **Purpose:** Add new domain concept for "abandoned" state +- **Changes:** + - Add new `TaskStatus.ABANDONED = 'abandoned'` constant + - OR add `abandoned: boolean` property to Task class (decision needed) + - Add helper method `canBeMarkedAsAbandoned()` to Task class that checks: + - `isOverdue()` returns true (already exists) + - Days overdue > 7 + - `priority !== TaskPriority.HIGH` (protects high-priority tasks) + +#### **storage.js** (HIGH PRIORITY) +- **Purpose:** Retrieve tasks matching the abandonment criteria +- **Changes:** + - Add `getTasksEligibleForAbandonment()` method that: + - Returns all tasks where `isOverdue() === true` + - Filters to those with dueDate older than 7 days + - Excludes high-priority tasks + - Excludes already-done or abandoned tasks + - Add `markTaskAsAbandoned(taskId)` method to transition task to abandoned state + +#### **app.js** (HIGH PRIORITY) +- **Purpose:** Implement business logic and orchestrate the abandonment process +- **Changes:** + - Add `abandonOverdueHighRiskTasks()` public method that: + - Calls `storage.getTasksEligibleForAbandonment()` + - Iterates through results and calls `updateTaskStatus(taskId, TaskStatus.ABANDONED)` + - Returns count of affected tasks for logging + - Add `updateTaskStatus()` wrapper to handle ABANDONED state transitions + - Consider: Should we log which tasks were abandoned? + +#### **cli.js** (MEDIUM PRIORITY) +- **Purpose:** Expose the abandonment process to users +- **Changes Option A (On-Demand):** + - Add new command: `program.command('cleanup-abandoned')` + - Calls `taskManager.abandonOverdueHighRiskTasks()` + - Displays count of tasks marked as abandoned + +- **Changes Option B (Automatic Check):** + - Call `taskManager.abandonOverdueHighRiskTasks()` on startup + - Call in `listTasks()` before returning results (keeps data fresh) + +--- + +### 2. Outline of Implementation Changes + +#### **Step 1: Domain Model Extension (models.js)** +```javascript +// Add to TaskStatus enumeration +const TaskStatus = { + TODO: 'todo', + IN_PROGRESS: 'in_progress', + REVIEW: 'review', + DONE: 'done', + ABANDONED: 'abandoned' // NEW +}; + +// Add method to Task class +canBeMarkedAsAbandoned() { + // Rule: overdue + not high priority + if (!this.isOverdue()) return false; // Not even overdue yet + if (this.priority === TaskPriority.HIGH) return false; // Protected by priority + + // Check if more than 7 days overdue + const daysOverdue = Math.floor( + (new Date() - this.dueDate) / (1000 * 60 * 60 * 24) + ); + return daysOverdue > 7; +} +``` + +#### **Step 2: Data Layer (storage.js)** +```javascript +// Add to TaskStorage class +getTasksEligibleForAbandonment() { + return Object.values(this.tasks).filter(task => + task.canBeMarkedAsAbandoned() + ); +} + +// Enhanced updateTask to handle abandoned state +updateTask(taskId, updates) { + const task = this.getTask(taskId); + if (task) { + if (updates.status === TaskStatus.ABANDONED) { + task.abandonedAt = new Date(); // Track when abandoned + } + task.update(updates); + this.save(); + return true; + } + return false; +} +``` + +#### **Step 3: Business Logic (app.js)** +```javascript +// Add to TaskManager class +abandonOverdueHighRiskTasks() { + const tasksToAbandon = this.storage.getTasksEligibleForAbandonment(); + const count = tasksToAbandon.length; + + tasksToAbandon.forEach(task => { + this.updateTaskStatus(task.id, TaskStatus.ABANDONED); + }); + + if (count > 0) { + console.log(`[SYSTEM] Marked ${count} task(s) as abandoned`); + } + + return count; +} +``` + +#### **Step 4: Presentation Layer (cli.js)** +```javascript +// Option A: On-demand command +program + .command('cleanup') + .description('Mark overdue tasks as abandoned (7+ days overdue, not high priority)') + .action(() => { + const count = taskManager.abandonOverdueHighRiskTasks(); + console.log(`Cleanup complete: ${count} task(s) marked as abandoned.`); + }); + +// Option B: Call on startup +// In the taskManager initialization or at the start of main execution: +taskManager.abandonOverdueHighRiskTasks(); +``` + +--- + +### 3. Questions for Your Team + +#### **Architectural Decisions** + +1. **When should this rule execute?** + - [ ] On every startup (automatic hygiene) + - [ ] On-demand via CLI command (user-triggered) + - [ ] Both (check on startup AND provide manual command) + - [ ] Periodically in the background (would need a scheduler) + +2. **Should "abandoned" be a new status or a flag?** + - Current approach: New status in TaskStatus enum + - Alternative: Keep status as-is, add `abandoned: boolean` property + - Why this matters: Abandoned affects filtering, reporting, and UI display + +3. **What about reverting abandoned tasks?** + - Can users manually change status back from ABANDONED → TODO? + - Should there be an "unabandoned" reason/comment? + - How do we prevent users from just re-abandoning the same task infinitely? + +4. **Should high-priority threshold be different?** + - Current rule: High priority tasks NEVER auto-abandon + - Alternative: High priority gets extended grace period (14 days instead of 7) + - What defines "high priority" in your business domain? + +5. **How does this affect statistics and reporting?** + - Should abandoned tasks be excluded from "overdue" counts? + - Should we have an "abandoned" category in stats? + - Impact on KPIs and dashboards? + +6. **What's the user notification strategy?** + - Should we email/notify users when their task is about to be abandoned? + - Should there be a "7-day warning" before auto-abandon? + - Or is this silent system maintenance? + +7. **Audit trail requirements:** + - Should we track WHO marked a task abandoned (system vs user)? + - Do we need to log the reason? + - Do we need `abandonedAt` timestamp (I assumed yes)? + +--- + +## Reflection + +### How Did the AI Prompts Help Understanding? + +✅ **Understanding Architectural Layers:** +- The three-layer model (CLI → Business Logic → Storage) made it immediately clear where each piece belongs +- Without this, I might have put all logic in cli.js or scattered across files +- Recognizing that each layer has a specific responsibility made the decision obvious + +✅ **Domain Model Thinking:** +- Framing this as a "business rule" rather than "code feature" helped identify that this is a new domain concept +- Understanding TaskStatus as a value object (restricted set) made it natural to add ABANDONED status +- Knowing that Task has behavior (isOverdue, markAsDone) made me think about adding a `canBeMarkedAsAbandoned()` method to the Task itself + +✅ **Understanding Dependencies:** +- Seeing that TaskManager depends on TaskStorage (not the other way) showed me that TaskManager should orchestrate the abandonment, not TaskStorage +- This prevents the storage layer from making business decisions + +✅ **Connection to Features:** +- Understanding how `listTasks()` works helped me see that I could hook abandonment logic there OR in a separate command +- Knowing existing commands helped me design the new CLI command consistently + +--- + +### Aspects Still Uncertain + +❓ **Uncertainty 1: State Transition Design** +- Should abandoned be a terminal state (like DONE)? +- Or can abandoned tasks transition back to TODO if user revives them? +- The current code seems to assume tasks flow: TODO → IN_PROGRESS → REVIEW → DONE +- Is abandonment a parallel state or part of this flow? + +❓ **Uncertainty 2: When to Check** +- On-demand vs automatic affects system design significantly +- If automatic (on startup), we need to ensure it runs BEFORE CLI commands execute +- If automatic (periodic), we need scheduler infrastructure I haven't seen +- The code doesn't show any scheduler or background job system + +❓ **Uncertainty 3: Data Migration** +- Do existing tasks that are already 8+ days overdue get retroactively abandoned? +- Or only new tasks going forward? +- This affects the implementation (might need a migration script) + +❓ **Uncertainty 4: Testing Time-Based Logic** +- How do we test "more than 7 days" without manipulating system time? +- Should dueDate be injectable for testing? +- Should we have a `isOverdueByDays(days)` method to test the boundary? + +❓ **Uncertainty 5: High Priority Definition** +- Is "high priority" always TaskPriority.HIGH? +- Or should we make it configurable (e.g., HIGH and URGENT never auto-abandon)? +- The business might want different rules later + +--- + +### Next Steps to Deepen Understanding + +**Step 1: Code Exploration (Review Complete Methods)** +- [ ] Read entire app.js to see all methods and how they use storage +- [ ] Read entire storage.js to understand all data retrieval patterns +- [ ] Look for any existing time-based or calculated methods (best practices) + +**Step 2: Pattern Matching** +- [ ] Find similar business rules in the code (e.g., isOverdue implementation) +- [ ] See how existing statuses are handled in updates +- [ ] Check how statistics method aggregates by status (template for our changes) + +**Step 3: Architecture Deep Dive** +- [ ] Trace a complete user command from CLI through all layers (e.g., `delete `) +- [ ] Understand the exact flow of data and state changes +- [ ] Identify any hooks or patterns for system-level operations + +**Step 4: Integration Points** +- [ ] Check if there's a main entry point or initialization pattern +- [ ] See if TaskManager is instantiated once or per command +- [ ] Understand when save() is called and how persistence works + +**Step 5: Ask Clarifying Questions** +- [ ] Ask team: Is this rule immediate need or future feature? +- [ ] Ask team: What triggers this rule in real usage? +- [ ] Ask team: Are there other similar auto-maintenance rules planned? + +**Step 6: Implementation Strategy** +- [ ] Start with models.js (add ABANDONED status and helper method) +- [ ] Add storage.js method to query eligible tasks +- [ ] Add app.js orchestration method +- [ ] Test in isolation with mock data +- [ ] Add CLI integration last (after business logic works) + +--- + +## Key Insights from This Exercise + +**1. Business Logic Belongs in the Domain:** +The `canBeMarkedAsAbandoned()` method belongs on the Task itself, not scattered in TaskManager. This keeps the rule close to the data it validates. + +**2. Layers Enable Flexibility:** +Because we have separate layers, we can implement the abandonment check as on-demand CLI command OR automatic startup cleanup with minimal changes—just where the method is called. + +**3. New Status = New Behavior:** +Adding ABANDONED to TaskStatus isn't just a naming thing—it affects filtering, sorting, reporting, and user experience. It's a first-class domain concept. + +**4. Questions Drive Design:** +The unanswered questions above aren't blockers—they're design opportunities. Each answer shapes the implementation. This is why senior developers ask "why" before coding. + diff --git a/use-cases/task-manager/javascript/submission.md b/use-cases/task-manager/javascript/submission.md new file mode 100644 index 00000000..8e6494f4 --- /dev/null +++ b/use-cases/task-manager/javascript/submission.md @@ -0,0 +1,28 @@ +# Final Submission + +## Initial Understanding vs Final Understanding +My initial understanding of the project was pretty accurate. I correctly identified the main files and their purposes. I also correctly identified the main components and technologies used in the project. My initial understanding of the project structure was also correct. +My final understanding of the project is that it is a simple task manager application that allows users to create, read, update, and delete tasks. The project uses a command line interface to interact with the user and stores data in a file. The main components of the project are the CLI tools and file pathing. The project uses the commander library for creating the CLI and uuidv4 for generating unique IDs for tasks. + +## Most value gained from each prompt +### Prompt 1 +This prompt was the most helpful as it helped me understand the overall structure of the project and the main components. It also helped me understand the technologies used in the project and how they fit together. +### Prompt 2 +This prompt was helpful in understanding where to find the code for the CSV export feature. It helped me identify which files and directories were most likely to contain the implementation for this feature and suggested specific search terms to use. It also helped me understand how the feature might be located in different areas of the codebase and recommended a step-by-step investigation process to understand the complete feature flow. +### Prompt 3 +This prompt was helpful in understanding the challenges I faced while exploring the codebase and how I overcame them. It also helped me reflect on the most useful prompts and what I would do differently in the future when exploring a new codebase. It also helped me identify additional tools that could have been helpful in my exploration. + +## Implementing new business rules +1. I would first read through the existing code to understand how the current business rules are implemented and where they are located in the codebase. +2. I would then identify where the new business rules need to be implemented and how they fit into the existing code structure. +3. I would write the code for the new business rules, making sure to follow the existing coding style and conventions used in the project. +4. I would then test the new business rules to ensure they work as expected and do not break any existing functionality. +5. Finally, I would document the new business rules and any changes made to the codebase to ensure that other developers can understand the changes and how to use the new features. + +## New startegies for unfimiliar codebases +1. Start with a high-level overview: Read the README and any documentation to get a general understanding of the project and its purpose. +2. Identify the main components: Look for the main files and directories in the codebase and try to understand their roles and how they interact with each other. +3. Use search strategically: Instead of searching for specific features, search for architectural patterns and keywords that can help you understand the structure of the codebase. +4. Trace data flow: Follow the flow of data through the codebase to understand how different components interact and where key functionalities are implemented. +5. Ask questions: Don't be afraid to ask your team for clarification on parts of the codebase that you don't understand. This can help you gain insights and learn from more experienced developers. +6. Use tools: Utilize code editors with good search capabilities, debuggers, and other tools that can help you navigate and understand the codebase more effectively. \ No newline at end of file