initial commit
This commit is contained in:
470
.claude/skills/functional-design/guide.md
Normal file
470
.claude/skills/functional-design/guide.md
Normal file
@ -0,0 +1,470 @@
|
||||
# Functional Design Document Creation Guide
|
||||
|
||||
This guide provides practical guidance for creating a functional design document based on a Product Requirements Document (PRD).
|
||||
|
||||
## Purpose of the Functional Design Document
|
||||
|
||||
The functional design document translates the "what to build" defined in the PRD into "how to realize it".
|
||||
|
||||
**Main Content**:
|
||||
- System architecture diagram
|
||||
- Data model
|
||||
- Component design
|
||||
- Algorithm design (if applicable)
|
||||
- UI design
|
||||
- Error handling
|
||||
|
||||
## Basic Creation Flow
|
||||
|
||||
### Step 1: Review the PRD
|
||||
|
||||
Before creating the functional design document, always review the PRD.
|
||||
|
||||
```
|
||||
Example prompt for having Claude Code create a functional design document from the PRD:
|
||||
|
||||
Create a functional design document based on the content of the PRD.
|
||||
In particular, focus on the priority P0 (MVP) features.
|
||||
```
|
||||
|
||||
### Step 2: Create the System Architecture Diagram
|
||||
|
||||
#### Using Mermaid Notation
|
||||
|
||||
Write the system architecture diagram using Mermaid notation.
|
||||
|
||||
**Example of a basic 3-tier architecture**:
|
||||
```mermaid
|
||||
graph TB
|
||||
User[User]
|
||||
CLI[CLI Layer]
|
||||
Service[Service Layer]
|
||||
Data[Data Layer]
|
||||
|
||||
User --> CLI
|
||||
CLI --> Service
|
||||
Service --> Data
|
||||
```
|
||||
|
||||
**A more detailed example**:
|
||||
```mermaid
|
||||
graph TB
|
||||
User[User]
|
||||
CLI[CLI Interface]
|
||||
Commander[Commander.js]
|
||||
TaskManager[TaskManager]
|
||||
PriorityEstimator[PriorityEstimator]
|
||||
FileStorage[FileStorage]
|
||||
JSON[(tasks.json)]
|
||||
|
||||
User --> CLI
|
||||
CLI --> Commander
|
||||
Commander --> TaskManager
|
||||
TaskManager --> PriorityEstimator
|
||||
TaskManager --> FileStorage
|
||||
FileStorage --> JSON
|
||||
```
|
||||
|
||||
### Step 3: Define the Data Model
|
||||
|
||||
#### Define Clearly with TypeScript Type Definitions
|
||||
|
||||
Define the data model using TypeScript interfaces.
|
||||
|
||||
**Example of a basic Task type**:
|
||||
```typescript
|
||||
interface Task {
|
||||
id: string; // UUID v4
|
||||
title: string; // 1-200 characters
|
||||
description?: string; // Optional, Markdown format
|
||||
status: TaskStatus; // 'todo' | 'in_progress' | 'completed'
|
||||
priority: TaskPriority; // 'high' | 'medium' | 'low'
|
||||
estimatedPriority?: TaskPriority; // Automatically estimated priority
|
||||
dueDate?: Date; // Due date
|
||||
createdAt: Date; // Creation timestamp
|
||||
updatedAt: Date; // Update timestamp
|
||||
statusHistory?: StatusChange[]; // Status change history
|
||||
}
|
||||
|
||||
type TaskStatus = 'todo' | 'in_progress' | 'completed';
|
||||
type TaskPriority = 'high' | 'medium' | 'low';
|
||||
|
||||
interface StatusChange {
|
||||
from: TaskStatus;
|
||||
to: TaskStatus;
|
||||
changedAt: Date;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Add a comment explaining each field
|
||||
- Clearly note constraints (character count, format, etc.)
|
||||
- Add `?` to optional fields
|
||||
- Improve readability with type aliases
|
||||
|
||||
#### Creating an ER Diagram
|
||||
|
||||
When there are multiple entities, show the relationships with an ER diagram.
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
TASK ||--o{ SUBTASK : has
|
||||
TASK ||--o{ TAG : has
|
||||
USER ||--o{ TASK : creates
|
||||
|
||||
TASK {
|
||||
string id PK
|
||||
string title
|
||||
string status
|
||||
datetime createdAt
|
||||
}
|
||||
SUBTASK {
|
||||
string id PK
|
||||
string taskId FK
|
||||
string title
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Component Design
|
||||
|
||||
Clarify the responsibilities of each layer.
|
||||
|
||||
#### CLI Layer
|
||||
|
||||
**Responsibility**: Accept user input, validation, display results
|
||||
|
||||
```typescript
|
||||
// CommandLineInterface
|
||||
class CLI {
|
||||
// Accept user input
|
||||
parseArguments(): Command;
|
||||
|
||||
// Display results
|
||||
displayResult(result: Result): void;
|
||||
|
||||
// Display errors
|
||||
displayError(error: Error): void;
|
||||
}
|
||||
```
|
||||
|
||||
#### Service Layer
|
||||
|
||||
**Responsibility**: Implement business logic
|
||||
|
||||
```typescript
|
||||
// TaskManager
|
||||
class TaskManager {
|
||||
// Create a task
|
||||
createTask(data: CreateTaskData): Task;
|
||||
|
||||
// Get the task list
|
||||
listTasks(filter?: FilterOptions): Task[];
|
||||
|
||||
// Update a task
|
||||
updateTask(id: string, data: UpdateTaskData): Task;
|
||||
|
||||
// Delete a task
|
||||
deleteTask(id: string): void;
|
||||
}
|
||||
```
|
||||
|
||||
#### Data Layer
|
||||
|
||||
**Responsibility**: Data persistence and retrieval
|
||||
|
||||
```typescript
|
||||
// FileStorage
|
||||
class FileStorage {
|
||||
// Save data
|
||||
save(data: any): void;
|
||||
|
||||
// Load data
|
||||
load(): any;
|
||||
|
||||
// Check whether the file exists
|
||||
exists(): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Algorithm Design (if applicable)
|
||||
|
||||
Design complex logic (e.g., automatic priority estimation) in detail.
|
||||
|
||||
#### Example of an Automatic Priority Estimation Algorithm
|
||||
|
||||
**Purpose**: Automatically estimate priority from a task's due date, creation timestamp, and status
|
||||
|
||||
**Calculation Logic**:
|
||||
|
||||
##### Step 1: Deadline Score Calculation (0-100 points)
|
||||
```
|
||||
- Overdue: 100 points (highest)
|
||||
- 0-3 days until due: 90 points
|
||||
- 4-7 days until due: 70 points
|
||||
- 8-14 days until due: 50 points
|
||||
- 14 or more days until due: 30 points
|
||||
- No due date set: 20 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateDeadlineScore(dueDate?: Date): number {
|
||||
if (!dueDate) return 20;
|
||||
|
||||
const now = new Date();
|
||||
const daysRemaining = Math.floor((dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysRemaining < 0) return 100; // Overdue
|
||||
if (daysRemaining <= 3) return 90;
|
||||
if (daysRemaining <= 7) return 70;
|
||||
if (daysRemaining <= 14) return 50;
|
||||
return 30;
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 2: Elapsed Time Score Calculation (0-100 points)
|
||||
```
|
||||
- 30 or more days since creation: 100 points (highest)
|
||||
- 21-30 days since creation: 80 points
|
||||
- 14-21 days since creation: 60 points
|
||||
- 7-14 days since creation: 40 points
|
||||
- Less than 7 days since creation: 20 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateAgeScore(createdAt: Date): number {
|
||||
const now = new Date();
|
||||
const daysOld = Math.floor((now.getTime() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysOld >= 30) return 100;
|
||||
if (daysOld >= 21) return 80;
|
||||
if (daysOld >= 14) return 60;
|
||||
if (daysOld >= 7) return 40;
|
||||
return 20;
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 3: Status Score Calculation (0-100 points)
|
||||
```
|
||||
- In progress (in_progress): 100 points (highest priority)
|
||||
- Not started (todo): 50 points
|
||||
- Completed (completed): 0 points
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateStatusScore(status: TaskStatus): number {
|
||||
if (status === 'in_progress') return 100;
|
||||
if (status === 'todo') return 50;
|
||||
return 0; // completed
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 4: Total Score Calculation
|
||||
|
||||
**Weighted Average**:
|
||||
```
|
||||
Total Score = (Deadline Score × 50%) + (Elapsed Time Score × 20%) + (Status Score × 30%)
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function calculateTotalScore(task: Task): number {
|
||||
const deadlineScore = calculateDeadlineScore(task.dueDate);
|
||||
const ageScore = calculateAgeScore(task.createdAt);
|
||||
const statusScore = calculateStatusScore(task.status);
|
||||
|
||||
return (deadlineScore * 0.5) + (ageScore * 0.2) + (statusScore * 0.3);
|
||||
}
|
||||
```
|
||||
|
||||
##### Step 5: Priority Classification
|
||||
|
||||
**Classification by Threshold**:
|
||||
```
|
||||
- 70 points or more: high (high priority)
|
||||
- 40-70 points: medium (medium priority)
|
||||
- Less than 40 points: low (low priority)
|
||||
```
|
||||
|
||||
**Formula**:
|
||||
```typescript
|
||||
function estimatePriority(task: Task): TaskPriority {
|
||||
const score = calculateTotalScore(task);
|
||||
|
||||
if (score >= 70) return 'high';
|
||||
if (score >= 40) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
```
|
||||
|
||||
**Complete Implementation Example**:
|
||||
```typescript
|
||||
class PriorityEstimator {
|
||||
estimate(task: Task): TaskPriority {
|
||||
const deadlineScore = this.calculateDeadlineScore(task.dueDate);
|
||||
const ageScore = this.calculateAgeScore(task.createdAt);
|
||||
const statusScore = this.calculateStatusScore(task.status);
|
||||
|
||||
const totalScore = (deadlineScore * 0.5) + (ageScore * 0.2) + (statusScore * 0.3);
|
||||
|
||||
if (totalScore >= 70) return 'high';
|
||||
if (totalScore >= 40) return 'medium';
|
||||
return 'low';
|
||||
}
|
||||
|
||||
private calculateDeadlineScore(dueDate?: Date): number {
|
||||
if (!dueDate) return 20;
|
||||
|
||||
const now = new Date();
|
||||
const daysRemaining = Math.floor((dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysRemaining < 0) return 100;
|
||||
if (daysRemaining <= 3) return 90;
|
||||
if (daysRemaining <= 7) return 70;
|
||||
if (daysRemaining <= 14) return 50;
|
||||
return 30;
|
||||
}
|
||||
|
||||
private calculateAgeScore(createdAt: Date): number {
|
||||
const now = new Date();
|
||||
const daysOld = Math.floor((now.getTime() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (daysOld >= 30) return 100;
|
||||
if (daysOld >= 21) return 80;
|
||||
if (daysOld >= 14) return 60;
|
||||
if (daysOld >= 7) return 40;
|
||||
return 20;
|
||||
}
|
||||
|
||||
private calculateStatusScore(status: TaskStatus): number {
|
||||
if (status === 'in_progress') return 100;
|
||||
if (status === 'todo') return 50;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: Use Case Diagram
|
||||
|
||||
Express the main use cases with sequence diagrams.
|
||||
|
||||
**Task Addition Flow**:
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CLI
|
||||
participant TaskManager
|
||||
participant PriorityEstimator
|
||||
participant FileStorage
|
||||
|
||||
User->>CLI: devtask add "task"
|
||||
CLI->>CLI: Validate input
|
||||
CLI->>TaskManager: createTask(data)
|
||||
TaskManager->>TaskManager: Create task object
|
||||
TaskManager->>PriorityEstimator: estimate(task)
|
||||
PriorityEstimator-->>TaskManager: Estimated priority
|
||||
TaskManager->>FileStorage: save(task)
|
||||
FileStorage-->>TaskManager: Success
|
||||
TaskManager-->>CLI: Created task
|
||||
CLI-->>User: "Task created (ID: xxx)"
|
||||
```
|
||||
|
||||
### Step 7: UI Design (if applicable)
|
||||
|
||||
For CLI tools, define table display and color coding.
|
||||
|
||||
#### Table Display
|
||||
|
||||
```
|
||||
┌──────────┬──────────────────┬────────────┬──────────┬───────────────┐
|
||||
│ ID │ Title │ Status │ Priority │ Due Date │
|
||||
├──────────┼──────────────────┼────────────┼──────────┼───────────────┤
|
||||
│ 7a5c6ff0 │ Buy milk on the │ Not started│ High │ 2025-11-05 │
|
||||
│ │ way home. │ │ │ (1 day left) │
|
||||
└──────────┴──────────────────┴────────────┴──────────┴───────────────┘
|
||||
```
|
||||
|
||||
#### Color Coding
|
||||
|
||||
**Status Color Coding**:
|
||||
- Completed (completed): green
|
||||
- In progress (in_progress): yellow
|
||||
- Not started (todo): white
|
||||
|
||||
**Priority Color Coding**:
|
||||
- High (high): red
|
||||
- Medium (medium): yellow
|
||||
- Low (low): blue
|
||||
|
||||
### Step 8: File Structure (if applicable)
|
||||
|
||||
Define the data storage format.
|
||||
|
||||
**Example: Data storage for a CLI tool**:
|
||||
```
|
||||
.devtask/
|
||||
├── tasks.json # Task data
|
||||
└── config.json # Configuration data
|
||||
```
|
||||
|
||||
**Example of tasks.json**:
|
||||
```json
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"id": "7a5c6ff0-5f55-474e-baf7-ea13624d73a4",
|
||||
"title": "Buy milk on the way home",
|
||||
"description": "",
|
||||
"status": "todo",
|
||||
"priority": "high",
|
||||
"estimatedPriority": "medium",
|
||||
"dueDate": "2025-11-05T00:00:00.000Z",
|
||||
"createdAt": "2025-11-04T10:00:00.000Z",
|
||||
"updatedAt": "2025-11-04T10:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Step 9: Error Handling
|
||||
|
||||
Define the types of errors and how to handle them.
|
||||
|
||||
| Error Category | Handling | Display to User |
|
||||
|-----------|------|-----------------|
|
||||
| Input validation error | Abort processing, display error message | "Please enter a title of 1-200 characters" |
|
||||
| File read error | Continue with empty initial data | "Data file not found. Creating a new one" |
|
||||
| Task not found | Abort processing, display error message | "Task not found (ID: xxx)" |
|
||||
|
||||
## Reviewing the Functional Design Document
|
||||
|
||||
### Review Perspectives
|
||||
|
||||
Request a review from Claude Code:
|
||||
|
||||
```
|
||||
Please evaluate this functional design document. Check it from the following perspectives:
|
||||
|
||||
1. Does it satisfy the requirements of the PRD?
|
||||
2. Is the data model concrete?
|
||||
3. Are the responsibilities of the components clear?
|
||||
4. Is the algorithm detailed to an implementable level?
|
||||
5. Is error handling comprehensive?
|
||||
```
|
||||
|
||||
### Implementing Improvements
|
||||
|
||||
Make improvements based on Claude Code's feedback.
|
||||
|
||||
## Summary
|
||||
|
||||
Keys to successfully creating a functional design document:
|
||||
|
||||
1. **Consistency with the PRD**: Accurately reflect the requirements defined in the PRD
|
||||
2. **Leverage Mermaid notation**: Express things visually with diagrams
|
||||
3. **TypeScript type definitions**: Make the data model clear
|
||||
4. **Detailed algorithm design**: Be concrete about complex logic
|
||||
5. **Layer separation**: Clarify the responsibilities of each component
|
||||
6. **Implementable level**: A level of detail that lets developers implement without confusion
|
||||
Reference in New Issue
Block a user