mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-20 02:15:12 +00:00
Merge pull request #601 from AungMyoKyaw/add-new-skills
Add 8 new skills for development tools and workflows
This commit is contained in:
@@ -24,16 +24,24 @@ Skills differ from other primitives by supporting bundled assets (scripts, code
|
||||
| ---- | ----------- | -------------- |
|
||||
| [appinsights-instrumentation](../skills/appinsights-instrumentation/SKILL.md) | Instrument a webapp to send useful telemetry data to Azure App Insights | `LICENSE.txt`<br />`examples/appinsights.bicep`<br />`references/ASPNETCORE.md`<br />`references/AUTO.md`<br />`references/NODEJS.md`<br />`references/PYTHON.md`<br />`scripts/appinsights.ps1` |
|
||||
| [azure-deployment-preflight](../skills/azure-deployment-preflight/SKILL.md) | Performs comprehensive preflight validation of Bicep deployments to Azure, including template syntax validation, what-if analysis, and permission checks. Use this skill before any deployment to Azure to preview changes, identify potential issues, and ensure the deployment will succeed. Activate when users mention deploying to Azure, validating Bicep files, checking deployment permissions, previewing infrastructure changes, running what-if, or preparing for azd provision. | `references/ERROR-HANDLING.md`<br />`references/REPORT-TEMPLATE.md`<br />`references/VALIDATION-COMMANDS.md` |
|
||||
| [azure-devops-cli](../skills/azure-devops-cli/SKILL.md) | Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI. | None |
|
||||
| [azure-resource-visualizer](../skills/azure-resource-visualizer/SKILL.md) | Analyze Azure resource groups and generate detailed Mermaid architecture diagrams showing the relationships between individual resources. Use this skill when the user asks for a diagram of their Azure resources or help in understanding how the resources relate to each other. | `LICENSE.txt`<br />`assets/template-architecture.md` |
|
||||
| [azure-role-selector](../skills/azure-role-selector/SKILL.md) | When user is asking for guidance for which role to assign to an identity given desired permissions, this agent helps them understand the role that will meet the requirements with least privilege access and how to apply that role. | `LICENSE.txt` |
|
||||
| [azure-static-web-apps](../skills/azure-static-web-apps/SKILL.md) | Helps create, configure, and deploy Azure Static Web Apps using the SWA CLI. Use when deploying static sites to Azure, setting up SWA local development, configuring staticwebapp.config.json, adding Azure Functions APIs to SWA, or setting up GitHub Actions CI/CD for Static Web Apps. | None |
|
||||
| [chrome-devtools](../skills/chrome-devtools/SKILL.md) | Expert-level browser automation, debugging, and performance analysis using Chrome DevTools MCP. Use for interacting with web pages, capturing screenshots, analyzing network traffic, and profiling performance. | None |
|
||||
| [gh-cli](../skills/gh-cli/SKILL.md) | GitHub CLI (gh) comprehensive reference for repositories, issues, pull requests, Actions, projects, releases, gists, codespaces, organizations, extensions, and all GitHub operations from the command line. | None |
|
||||
| [git-commit](../skills/git-commit/SKILL.md) | Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping | None |
|
||||
| [github-issues](../skills/github-issues/SKILL.md) | Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, or manage issue workflows. Triggers on requests like "create an issue", "file a bug", "request a feature", "update issue X", or any GitHub issue management task. | `references/templates.md` |
|
||||
| [image-manipulation-image-magick](../skills/image-manipulation-image-magick/SKILL.md) | Process and manipulate images using ImageMagick. Supports resizing, format conversion, batch processing, and retrieving image metadata. Use when working with images, creating thumbnails, resizing wallpapers, or performing batch image operations. | None |
|
||||
| [legacy-circuit-mockups](../skills/legacy-circuit-mockups/SKILL.md) | Generate breadboard circuit mockups and visual diagrams using HTML5 Canvas drawing techniques. Use when asked to create circuit layouts, visualize electronic component placements, draw breadboard diagrams, mockup 6502 builds, generate retro computer schematics, or design vintage electronics projects. Supports 555 timers, W65C02S microprocessors, 28C256 EEPROMs, W65C22 VIA chips, 7400-series logic gates, LEDs, resistors, capacitors, switches, buttons, crystals, and wires. | `references/28256-eeprom.md`<br />`references/555.md`<br />`references/6502.md`<br />`references/6522.md`<br />`references/6C62256.md`<br />`references/7400-series.md`<br />`references/assembly-compiler.md`<br />`references/assembly-language.md`<br />`references/basic-electronic-components.md`<br />`references/breadboard.md`<br />`references/common-breadboard-components.md`<br />`references/connecting-electronic-components.md`<br />`references/emulator-28256-eeprom.md`<br />`references/emulator-6502.md`<br />`references/emulator-6522.md`<br />`references/emulator-6C62256.md`<br />`references/emulator-lcd.md`<br />`references/lcd.md`<br />`references/minipro.md`<br />`references/t48eeprom-programmer.md` |
|
||||
| [make-skill-template](../skills/make-skill-template/SKILL.md) | Create new Agent Skills for GitHub Copilot from prompts or by duplicating this template. Use when asked to "create a skill", "make a new skill", "scaffold a skill", or when building specialized AI capabilities with bundled resources. Generates SKILL.md files with proper frontmatter, directory structure, and optional scripts/references/assets folders. | None |
|
||||
| [mcp-cli](../skills/mcp-cli/SKILL.md) | Interface for MCP (Model Context Protocol) servers via CLI. Use when you need to interact with external tools, APIs, or data sources through MCP servers, list available MCP servers/tools, or call MCP tools from command line. | None |
|
||||
| [microsoft-code-reference](../skills/microsoft-code-reference/SKILL.md) | Look up Microsoft API references, find working code samples, and verify SDK code is correct. Use when working with Azure SDKs, .NET libraries, or Microsoft APIs—to find the right method, check parameters, get working examples, or troubleshoot errors. Catches hallucinated methods, wrong signatures, and deprecated patterns by querying official docs. | None |
|
||||
| [microsoft-docs](../skills/microsoft-docs/SKILL.md) | Query official Microsoft documentation to understand concepts, find tutorials, and learn how services work. Use for Azure, .NET, Microsoft 365, Windows, Power Platform, and all Microsoft technologies. Get accurate, current information from learn.microsoft.com and other official Microsoft websites—architecture overviews, quickstarts, configuration guides, limits, and best practices. | None |
|
||||
| [nuget-manager](../skills/nuget-manager/SKILL.md) | Manage NuGet packages in .NET projects/solutions. Use this skill when adding, removing, or updating NuGet package versions. It enforces using `dotnet` CLI for package management and provides strict procedures for direct file edits only when updating versions. | None |
|
||||
| [plantuml-ascii](../skills/plantuml-ascii/SKILL.md) | Generate ASCII art diagrams using PlantUML text mode. Use when user asks to create ASCII diagrams, text-based diagrams, terminal-friendly diagrams, or mentions plantuml ascii, text diagram, ascii art diagram. Supports: Converting PlantUML diagrams to ASCII art, Creating sequence diagrams, class diagrams, flowcharts in ASCII format, Generating Unicode-enhanced ASCII art with -utxt flag | None |
|
||||
| [prd](../skills/prd/SKILL.md) | Generate high-quality Product Requirements Documents (PRDs) for software systems and AI-powered features. Includes executive summaries, user stories, technical specifications, and risk analysis. | None |
|
||||
| [refactor](../skills/refactor/SKILL.md) | Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements. | None |
|
||||
| [snowflake-semanticview](../skills/snowflake-semanticview/SKILL.md) | Create, alter, and validate Snowflake semantic views using Snowflake CLI (snow). Use when asked to build or troubleshoot semantic views/semantic layer definitions with CREATE/ALTER SEMANTIC VIEW, to validate semantic-view DDL against Snowflake via CLI, or to guide Snowflake CLI installation and connection setup. | None |
|
||||
| [vscode-ext-commands](../skills/vscode-ext-commands/SKILL.md) | Guidelines for contributing commands in VS Code extensions. Indicates naming convention, visibility, localization and other relevant attributes, following VS Code extension development guidelines, libraries and good practices | None |
|
||||
| [vscode-ext-localization](../skills/vscode-ext-localization/SKILL.md) | Guidelines for proper localization of VS Code extensions, following VS Code extension development guidelines, libraries and good practices | None |
|
||||
|
||||
2467
skills/azure-devops-cli/SKILL.md
Normal file
2467
skills/azure-devops-cli/SKILL.md
Normal file
File diff suppressed because it is too large
Load Diff
97
skills/chrome-devtools/SKILL.md
Normal file
97
skills/chrome-devtools/SKILL.md
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
name: chrome-devtools
|
||||
description: 'Expert-level browser automation, debugging, and performance analysis using Chrome DevTools MCP. Use for interacting with web pages, capturing screenshots, analyzing network traffic, and profiling performance.'
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Chrome DevTools Agent
|
||||
|
||||
## Overview
|
||||
|
||||
A specialized skill for controlling and inspecting a live Chrome browser. This skill leverages the `chrome-devtools` MCP server to perform a wide range of browser-related tasks, from simple navigation to complex performance profiling.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when:
|
||||
|
||||
- **Browser Automation**: Navigating pages, clicking elements, filling forms, and handling dialogs.
|
||||
- **Visual Inspection**: Taking screenshots or text snapshots of web pages.
|
||||
- **Debugging**: Inspecting console messages, evaluating JavaScript in the page context, and analyzing network requests.
|
||||
- **Performance Analysis**: Recording and analyzing performance traces to identify bottlenecks and Core Web Vital issues.
|
||||
- **Emulation**: Resizing the viewport or emulating network/CPU conditions.
|
||||
|
||||
## Tool Categories
|
||||
|
||||
### 1. Navigation & Page Management
|
||||
|
||||
- `new_page`: Open a new tab/page.
|
||||
- `navigate_page`: Go to a specific URL, reload, or navigate history.
|
||||
- `select_page`: Switch context between open pages.
|
||||
- `list_pages`: See all open pages and their IDs.
|
||||
- `close_page`: Close a specific page.
|
||||
- `wait_for`: Wait for specific text to appear on the page.
|
||||
|
||||
### 2. Input & Interaction
|
||||
|
||||
- `click`: Click on an element (use `uid` from snapshot).
|
||||
- `fill` / `fill_form`: Type text into inputs or fill multiple fields at once.
|
||||
- `hover`: Move the mouse over an element.
|
||||
- `press_key`: Send keyboard shortcuts or special keys (e.g., "Enter", "Control+C").
|
||||
- `drag`: Drag and drop elements.
|
||||
- `handle_dialog`: Accept or dismiss browser alerts/prompts.
|
||||
- `upload_file`: Upload a file through a file input.
|
||||
|
||||
### 3. Debugging & Inspection
|
||||
|
||||
- `take_snapshot`: Get a text-based accessibility tree (best for identifying elements).
|
||||
- `take_screenshot`: Capture a visual representation of the page or a specific element.
|
||||
- `list_console_messages` / `get_console_message`: Inspect the page's console output.
|
||||
- `evaluate_script`: Run custom JavaScript in the page context.
|
||||
- `list_network_requests` / `get_network_request`: Analyze network traffic and request details.
|
||||
|
||||
### 4. Emulation & Performance
|
||||
|
||||
- `resize_page`: Change the viewport dimensions.
|
||||
- `emulate`: Throttling CPU/Network or emulating geolocation.
|
||||
- `performance_start_trace`: Start recording a performance profile.
|
||||
- `performance_stop_trace`: Stop recording and save the trace.
|
||||
- `performance_analyze_insight`: Get detailed analysis from recorded performance data.
|
||||
|
||||
## Workflow Patterns
|
||||
|
||||
### Pattern A: Identifying Elements (Snapshot-First)
|
||||
|
||||
Always prefer `take_snapshot` over `take_screenshot` for finding elements. The snapshot provides `uid` values which are required by interaction tools.
|
||||
|
||||
```markdown
|
||||
1. `take_snapshot` to get the current page structure.
|
||||
2. Find the `uid` of the target element.
|
||||
3. Use `click(uid=...)` or `fill(uid=..., value=...)`.
|
||||
```
|
||||
|
||||
### Pattern B: Troubleshooting Errors
|
||||
|
||||
When a page is failing, check both console logs and network requests.
|
||||
|
||||
```markdown
|
||||
1. `list_console_messages` to check for JavaScript errors.
|
||||
2. `list_network_requests` to identify failed (4xx/5xx) resources.
|
||||
3. `evaluate_script` to check the value of specific DOM elements or global variables.
|
||||
```
|
||||
|
||||
### Pattern C: Performance Profiling
|
||||
|
||||
Identify why a page is slow.
|
||||
|
||||
```markdown
|
||||
1. `performance_start_trace(reload=true, autoStop=true)`
|
||||
2. Wait for the page to load/trace to finish.
|
||||
3. `performance_analyze_insight` to find LCP issues or layout shifts.
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Context Awareness**: Always run `list_pages` and `select_page` if you are unsure which tab is currently active.
|
||||
- **Snapshots**: Take a new snapshot after any major navigation or DOM change, as `uid` values may change.
|
||||
- **Timeouts**: Use reasonable timeouts for `wait_for` to avoid hanging on slow-loading elements.
|
||||
- **Screenshots**: Use `take_screenshot` sparingly for visual verification, but rely on `take_snapshot` for logic.
|
||||
2189
skills/gh-cli/SKILL.md
Normal file
2189
skills/gh-cli/SKILL.md
Normal file
File diff suppressed because it is too large
Load Diff
124
skills/git-commit/SKILL.md
Normal file
124
skills/git-commit/SKILL.md
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
name: git-commit
|
||||
description: 'Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping'
|
||||
license: MIT
|
||||
allowed-tools: Bash
|
||||
---
|
||||
|
||||
# Git Commit with Conventional Commits
|
||||
|
||||
## Overview
|
||||
|
||||
Create standardized, semantic git commits using the Conventional Commits specification. Analyze the actual diff to determine appropriate type, scope, and message.
|
||||
|
||||
## Conventional Commit Format
|
||||
|
||||
```
|
||||
<type>[optional scope]: <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer(s)]
|
||||
```
|
||||
|
||||
## Commit Types
|
||||
|
||||
| Type | Purpose |
|
||||
| ---------- | ------------------------------ |
|
||||
| `feat` | New feature |
|
||||
| `fix` | Bug fix |
|
||||
| `docs` | Documentation only |
|
||||
| `style` | Formatting/style (no logic) |
|
||||
| `refactor` | Code refactor (no feature/fix) |
|
||||
| `perf` | Performance improvement |
|
||||
| `test` | Add/update tests |
|
||||
| `build` | Build system/dependencies |
|
||||
| `ci` | CI/config changes |
|
||||
| `chore` | Maintenance/misc |
|
||||
| `revert` | Revert commit |
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
```
|
||||
# Exclamation mark after type/scope
|
||||
feat!: remove deprecated endpoint
|
||||
|
||||
# BREAKING CHANGE footer
|
||||
feat: allow config to extend other configs
|
||||
|
||||
BREAKING CHANGE: `extends` key behavior changed
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Analyze Diff
|
||||
|
||||
```bash
|
||||
# If files are staged, use staged diff
|
||||
git diff --staged
|
||||
|
||||
# If nothing staged, use working tree diff
|
||||
git diff
|
||||
|
||||
# Also check status
|
||||
git status --porcelain
|
||||
```
|
||||
|
||||
### 2. Stage Files (if needed)
|
||||
|
||||
If nothing is staged or you want to group changes differently:
|
||||
|
||||
```bash
|
||||
# Stage specific files
|
||||
git add path/to/file1 path/to/file2
|
||||
|
||||
# Stage by pattern
|
||||
git add *.test.*
|
||||
git add src/components/*
|
||||
|
||||
# Interactive staging
|
||||
git add -p
|
||||
```
|
||||
|
||||
**Never commit secrets** (.env, credentials.json, private keys).
|
||||
|
||||
### 3. Generate Commit Message
|
||||
|
||||
Analyze the diff to determine:
|
||||
|
||||
- **Type**: What kind of change is this?
|
||||
- **Scope**: What area/module is affected?
|
||||
- **Description**: One-line summary of what changed (present tense, imperative mood, <72 chars)
|
||||
|
||||
### 4. Execute Commit
|
||||
|
||||
```bash
|
||||
# Single line
|
||||
git commit -m "<type>[scope]: <description>"
|
||||
|
||||
# Multi-line with body/footer
|
||||
git commit -m "$(cat <<'EOF'
|
||||
<type>[scope]: <description>
|
||||
|
||||
<optional body>
|
||||
|
||||
<optional footer>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- One logical change per commit
|
||||
- Present tense: "add" not "added"
|
||||
- Imperative mood: "fix bug" not "fixes bug"
|
||||
- Reference issues: `Closes #123`, `Refs #456`
|
||||
- Keep description under 72 characters
|
||||
|
||||
## Git Safety Protocol
|
||||
|
||||
- NEVER update git config
|
||||
- NEVER run destructive commands (--force, hard reset) without explicit request
|
||||
- NEVER skip hooks (--no-verify) unless user asks
|
||||
- NEVER force push to main/master
|
||||
- If commit fails due to hooks, fix and create NEW commit (don't amend)
|
||||
78
skills/mcp-cli/SKILL.md
Normal file
78
skills/mcp-cli/SKILL.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
name: mcp-cli
|
||||
description: Interface for MCP (Model Context Protocol) servers via CLI. Use when you need to interact with external tools, APIs, or data sources through MCP servers, list available MCP servers/tools, or call MCP tools from command line.
|
||||
---
|
||||
|
||||
# MCP-CLI
|
||||
|
||||
Access MCP servers through the command line. MCP enables interaction with external systems like GitHub, filesystems, databases, and APIs.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Output |
|
||||
| ---------------------------------- | ------------------------------- |
|
||||
| `mcp-cli` | List all servers and tool names |
|
||||
| `mcp-cli <server>` | Show tools with parameters |
|
||||
| `mcp-cli <server>/<tool>` | Get tool JSON schema |
|
||||
| `mcp-cli <server>/<tool> '<json>'` | Call tool with arguments |
|
||||
| `mcp-cli grep "<glob>"` | Search tools by name |
|
||||
|
||||
**Add `-d` to include descriptions** (e.g., `mcp-cli filesystem -d`)
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Discover**: `mcp-cli` → see available servers and tools
|
||||
2. **Explore**: `mcp-cli <server>` → see tools with parameters
|
||||
3. **Inspect**: `mcp-cli <server>/<tool>` → get full JSON input schema
|
||||
4. **Execute**: `mcp-cli <server>/<tool> '<json>'` → run with arguments
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# List all servers and tool names
|
||||
mcp-cli
|
||||
|
||||
# See all tools with parameters
|
||||
mcp-cli filesystem
|
||||
|
||||
# With descriptions (more verbose)
|
||||
mcp-cli filesystem -d
|
||||
|
||||
# Get JSON schema for specific tool
|
||||
mcp-cli filesystem/read_file
|
||||
|
||||
# Call the tool
|
||||
mcp-cli filesystem/read_file '{"path": "./README.md"}'
|
||||
|
||||
# Search for tools
|
||||
mcp-cli grep "*file*"
|
||||
|
||||
# JSON output for parsing
|
||||
mcp-cli filesystem/read_file '{"path": "./README.md"}' --json
|
||||
|
||||
# Complex JSON with quotes (use heredoc or stdin)
|
||||
mcp-cli server/tool <<EOF
|
||||
{"content": "Text with 'quotes' inside"}
|
||||
EOF
|
||||
|
||||
# Or pipe from a file/command
|
||||
cat args.json | mcp-cli server/tool
|
||||
|
||||
# Find all TypeScript files and read the first one
|
||||
mcp-cli filesystem/search_files '{"path": "src/", "pattern": "*.ts"}' --json | jq -r '.content[0].text' | head -1 | xargs -I {} sh -c 'mcp-cli filesystem/read_file "{\"path\": \"{}\"}"'
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
| Flag | Purpose |
|
||||
| ------------ | ------------------------- |
|
||||
| `-j, --json` | JSON output for scripting |
|
||||
| `-r, --raw` | Raw text content |
|
||||
| `-d` | Include descriptions |
|
||||
|
||||
## Exit Codes
|
||||
|
||||
- `0`: Success
|
||||
- `1`: Client error (bad args, missing config)
|
||||
- `2`: Server error (tool failed)
|
||||
- `3`: Network error
|
||||
305
skills/plantuml-ascii/SKILL.md
Normal file
305
skills/plantuml-ascii/SKILL.md
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
name: plantuml-ascii
|
||||
description: "Generate ASCII art diagrams using PlantUML text mode. Use when user asks to create ASCII diagrams, text-based diagrams, terminal-friendly diagrams, or mentions plantuml ascii, text diagram, ascii art diagram. Supports: Converting PlantUML diagrams to ASCII art, Creating sequence diagrams, class diagrams, flowcharts in ASCII format, Generating Unicode-enhanced ASCII art with -utxt flag"
|
||||
license: MIT
|
||||
allowed-tools: Bash, Write, Read
|
||||
---
|
||||
|
||||
# PlantUML ASCII Art Diagram Generator
|
||||
|
||||
## Overview
|
||||
|
||||
Create text-based ASCII art diagrams using PlantUML. Perfect for documentation in terminal environments, README files, emails, or any scenario where graphical diagrams aren't suitable.
|
||||
|
||||
## What is PlantUML ASCII Art?
|
||||
|
||||
PlantUML can generate diagrams as plain text (ASCII art) instead of images. This is useful for:
|
||||
|
||||
- Terminal-based workflows
|
||||
- Git commits/PRs without image support
|
||||
- Documentation that needs to be version-controlled
|
||||
- Environments where graphical tools aren't available
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
brew install plantuml
|
||||
|
||||
# Linux (varies by distro)
|
||||
sudo apt-get install plantuml # Ubuntu/Debian
|
||||
sudo yum install plantuml # RHEL/CentOS
|
||||
|
||||
# Or download JAR directly
|
||||
wget https://github.com/plantuml/plantuml/releases/download/v1.2024.0/plantuml-1.2024.0.jar
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
| Flag | Format | Description |
|
||||
| ------- | ------------- | ------------------------------------ |
|
||||
| `-txt` | ASCII | Pure ASCII characters |
|
||||
| `-utxt` | Unicode ASCII | Enhanced with box-drawing characters |
|
||||
|
||||
## Basic Workflow
|
||||
|
||||
### 1. Create PlantUML Diagram File
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
participant Bob
|
||||
actor Alice
|
||||
|
||||
Bob -> Alice : hello
|
||||
Alice -> Bob : Is it ok?
|
||||
@enduml
|
||||
```
|
||||
|
||||
### 2. Generate ASCII Art
|
||||
|
||||
```bash
|
||||
# Standard ASCII output
|
||||
plantuml -txt diagram.puml
|
||||
|
||||
# Unicode-enhanced output (better looking)
|
||||
plantuml -utxt diagram.puml
|
||||
|
||||
# Using JAR directly
|
||||
java -jar plantuml.jar -txt diagram.puml
|
||||
java -jar plantuml.jar -utxt diagram.puml
|
||||
```
|
||||
|
||||
### 3. View Output
|
||||
|
||||
Output is saved as `diagram.atxt` (ASCII) or `diagram.utxt` (Unicode).
|
||||
|
||||
## Diagram Types Supported
|
||||
|
||||
### Sequence Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
actor User
|
||||
participant "Web App" as App
|
||||
database "Database" as DB
|
||||
|
||||
User -> App : Login Request
|
||||
App -> DB : Validate Credentials
|
||||
DB --> App : User Data
|
||||
App --> User : Auth Token
|
||||
@enduml
|
||||
```
|
||||
|
||||
### Class Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
class User {
|
||||
+id: int
|
||||
+name: string
|
||||
+email: string
|
||||
+login(): bool
|
||||
}
|
||||
|
||||
class Order {
|
||||
+id: int
|
||||
+total: float
|
||||
+items: List
|
||||
+calculateTotal(): float
|
||||
}
|
||||
|
||||
User "1" -- "*" Order : places
|
||||
@enduml
|
||||
```
|
||||
|
||||
### Activity Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
start
|
||||
:Initialize;
|
||||
if (Is Valid?) then (yes)
|
||||
:Process Data;
|
||||
:Save Result;
|
||||
else (no)
|
||||
:Log Error;
|
||||
stop
|
||||
endif
|
||||
:Complete;
|
||||
stop
|
||||
@enduml
|
||||
```
|
||||
|
||||
### State Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
[*] --> Idle
|
||||
Idle --> Processing : start
|
||||
Processing --> Success : complete
|
||||
Processing --> Error : fail
|
||||
Success --> [*]
|
||||
Error --> Idle : retry
|
||||
@enduml
|
||||
```
|
||||
|
||||
### Component Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
[Client] as client
|
||||
[API Gateway] as gateway
|
||||
[Service A] as svcA
|
||||
[Service B] as svcB
|
||||
[Database] as db
|
||||
|
||||
client --> gateway
|
||||
gateway --> svcA
|
||||
gateway --> svcB
|
||||
svcA --> db
|
||||
svcB --> db
|
||||
@enduml
|
||||
```
|
||||
|
||||
### Use Case Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
actor "User" as user
|
||||
actor "Admin" as admin
|
||||
|
||||
rectangle "System" {
|
||||
user -- (Login)
|
||||
user -- (View Profile)
|
||||
user -- (Update Settings)
|
||||
admin -- (Manage Users)
|
||||
admin -- (Configure System)
|
||||
}
|
||||
@enduml
|
||||
```
|
||||
|
||||
### Deployment Diagram
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
actor "User" as user
|
||||
node "Load Balancer" as lb
|
||||
node "Web Server 1" as ws1
|
||||
node "Web Server 2" as ws2
|
||||
database "Primary DB" as db1
|
||||
database "Replica DB" as db2
|
||||
|
||||
user --> lb
|
||||
lb --> ws1
|
||||
lb --> ws2
|
||||
ws1 --> db1
|
||||
ws2 --> db1
|
||||
db1 --> db2 : replicate
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Command-Line Options
|
||||
|
||||
```bash
|
||||
# Specify output directory
|
||||
plantuml -txt -o ./output diagram.puml
|
||||
|
||||
# Process all files in directory
|
||||
plantuml -txt ./diagrams/
|
||||
|
||||
# Include dot files (hidden files)
|
||||
plantuml -txt -includeDot diagrams/
|
||||
|
||||
# Verbose output
|
||||
plantuml -txt -v diagram.puml
|
||||
|
||||
# Specify charset
|
||||
plantuml -txt -charset UTF-8 diagram.puml
|
||||
```
|
||||
|
||||
## Ant Task Integration
|
||||
|
||||
```xml
|
||||
<target name="generate-ascii">
|
||||
<plantuml dir="./src" format="txt" />
|
||||
</target>
|
||||
|
||||
<target name="generate-unicode-ascii">
|
||||
<plantuml dir="./src" format="utxt" />
|
||||
</target>
|
||||
```
|
||||
|
||||
## Tips for Better ASCII Diagrams
|
||||
|
||||
1. **Keep it simple**: Complex diagrams don't render well in ASCII
|
||||
2. **Short labels**: Long text breaks ASCII alignment
|
||||
3. **Use Unicode (`-utxt`)**: Better visual quality with box-drawing chars
|
||||
4. **Test before sharing**: Verify in terminal with fixed-width font
|
||||
5. **Consider alternatives**: For complex diagrams, use Mermaid.js or graphviz
|
||||
|
||||
## Example Output Comparison
|
||||
|
||||
**Standard ASCII (`-txt`)**:
|
||||
|
||||
```
|
||||
,---. ,---.
|
||||
|Bob| |Alice|
|
||||
`---' `---'
|
||||
| hello |
|
||||
|------------->|
|
||||
| |
|
||||
| Is it ok? |
|
||||
|<-------------|
|
||||
| |
|
||||
```
|
||||
|
||||
**Unicode ASCII (`-utxt`)**:
|
||||
|
||||
```
|
||||
┌─────┐ ┌─────┐
|
||||
│ Bob │ │Alice│
|
||||
└─────┘ └─────┘
|
||||
│ hello │
|
||||
│─────────────>│
|
||||
│ │
|
||||
│ Is it ok? │
|
||||
│<─────────────│
|
||||
│ │
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Create sequence diagram in ASCII
|
||||
cat > seq.puml << 'EOF'
|
||||
@startuml
|
||||
Alice -> Bob: Request
|
||||
Bob --> Alice: Response
|
||||
@enduml
|
||||
EOF
|
||||
|
||||
plantuml -txt seq.puml
|
||||
cat seq.atxt
|
||||
|
||||
# Create with Unicode
|
||||
plantuml -utxt seq.puml
|
||||
cat seq.utxt
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Problem**: Garbled Unicode characters
|
||||
|
||||
- **Solution**: Ensure terminal supports UTF-8 and has proper font
|
||||
|
||||
**Problem**: Diagram looks misaligned
|
||||
|
||||
- **Solution**: Use fixed-width font (Courier, Monaco, Consolas)
|
||||
|
||||
**Problem**: Command not found
|
||||
|
||||
- **Solution**: Install PlantUML or use Java JAR directly
|
||||
|
||||
**Problem**: Output file not created
|
||||
|
||||
- **Solution**: Check file permissions, ensure PlantUML has write access
|
||||
143
skills/prd/SKILL.md
Normal file
143
skills/prd/SKILL.md
Normal file
@@ -0,0 +1,143 @@
|
||||
---
|
||||
name: prd
|
||||
description: 'Generate high-quality Product Requirements Documents (PRDs) for software systems and AI-powered features. Includes executive summaries, user stories, technical specifications, and risk analysis.'
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Product Requirements Document (PRD)
|
||||
|
||||
## Overview
|
||||
|
||||
Design comprehensive, production-grade Product Requirements Documents (PRDs) that bridge the gap between business vision and technical execution. This skill works for modern software systems, ensuring that requirements are clearly defined.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when:
|
||||
|
||||
- Starting a new product or feature development cycle
|
||||
- Translating a vague idea into a concrete technical specification
|
||||
- Defining requirements for AI-powered features
|
||||
- Stakeholders need a unified "source of truth" for project scope
|
||||
- User asks to "write a PRD", "document requirements", or "plan a feature"
|
||||
|
||||
---
|
||||
|
||||
## Operational Workflow
|
||||
|
||||
### Phase 1: Discovery (The Interview)
|
||||
|
||||
Before writing a single line of the PRD, you **MUST** interrogate the user to fill knowledge gaps. Do not assume context.
|
||||
|
||||
**Ask about:**
|
||||
|
||||
- **The Core Problem**: Why are we building this now?
|
||||
- **Success Metrics**: How do we know it worked?
|
||||
- **Constraints**: Budget, tech stack, or deadline?
|
||||
|
||||
### Phase 2: Analysis & Scoping
|
||||
|
||||
Synthesize the user's input. Identify dependencies and hidden complexities.
|
||||
|
||||
- Map out the **User Flow**.
|
||||
- Define **Non-Goals** to protect the timeline.
|
||||
|
||||
### Phase 3: Technical Drafting
|
||||
|
||||
Generate the document using the **Strict PRD Schema** below.
|
||||
|
||||
---
|
||||
|
||||
## PRD Quality Standards
|
||||
|
||||
### Requirements Quality
|
||||
|
||||
Use concrete, measurable criteria. Avoid "fast", "easy", or "intuitive".
|
||||
|
||||
```diff
|
||||
# Vague (BAD)
|
||||
- The search should be fast and return relevant results.
|
||||
- The UI must look modern and be easy to use.
|
||||
|
||||
# Concrete (GOOD)
|
||||
+ The search must return results within 200ms for a 10k record dataset.
|
||||
+ The search algorithm must achieve >= 85% Precision@10 in benchmark evals.
|
||||
+ The UI must follow the 'Vercel/Next.js' design system and achieve 100% Lighthouse Accessibility score.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Strict PRD Schema
|
||||
|
||||
You **MUST** follow this exact structure for the output:
|
||||
|
||||
### 1. Executive Summary
|
||||
|
||||
- **Problem Statement**: 1-2 sentences on the pain point.
|
||||
- **Proposed Solution**: 1-2 sentences on the fix.
|
||||
- **Success Criteria**: 3-5 measurable KPIs.
|
||||
|
||||
### 2. User Experience & Functionality
|
||||
|
||||
- **User Personas**: Who is this for?
|
||||
- **User Stories**: `As a [user], I want to [action] so that [benefit].`
|
||||
- **Acceptance Criteria**: Bulleted list of "Done" definitions for each story.
|
||||
- **Non-Goals**: What are we NOT building?
|
||||
|
||||
### 3. AI System Requirements (If Applicable)
|
||||
|
||||
- **Tool Requirements**: What tools and APIs are needed?
|
||||
- **Evaluation Strategy**: How to measure output quality and accuracy.
|
||||
|
||||
### 4. Technical Specifications
|
||||
|
||||
- **Architecture Overview**: Data flow and component interaction.
|
||||
- **Integration Points**: APIs, DBs, and Auth.
|
||||
- **Security & Privacy**: Data handling and compliance.
|
||||
|
||||
### 5. Risks & Roadmap
|
||||
|
||||
- **Phased Rollout**: MVP -> v1.1 -> v2.0.
|
||||
- **Technical Risks**: Latency, cost, or dependency failures.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### DO (Always)
|
||||
|
||||
- **Define Testing**: For AI systems, specify how to test and validate output quality.
|
||||
- **Iterate**: Present a draft and ask for feedback on specific sections.
|
||||
|
||||
### DON'T (Avoid)
|
||||
|
||||
- **Skip Discovery**: Never write a PRD without asking at least 2 clarifying questions first.
|
||||
- **Hallucinate Constraints**: If the user didn't specify a tech stack, ask or label it as `TBD`.
|
||||
|
||||
---
|
||||
|
||||
## Example: Intelligent Search System
|
||||
|
||||
### 1. Executive Summary
|
||||
|
||||
**Problem**: Users struggle to find specific documentation snippets in massive repositories.
|
||||
**Solution**: An intelligent search system that provides direct answers with source citations.
|
||||
**Success**:
|
||||
|
||||
- Reduce search time by 50%.
|
||||
- Citation accuracy >= 95%.
|
||||
|
||||
### 2. User Stories
|
||||
|
||||
- **Story**: As a developer, I want to ask natural language questions so I don't have to guess keywords.
|
||||
- **AC**:
|
||||
- Supports multi-turn clarification.
|
||||
- Returns code blocks with "Copy" button.
|
||||
|
||||
### 3. AI System Architecture
|
||||
|
||||
- **Tools Required**: `codesearch`, `grep`, `webfetch`.
|
||||
|
||||
### 4. Evaluation
|
||||
|
||||
- **Benchmark**: Test with 50 common developer questions.
|
||||
- **Pass Rate**: 90% must match expected citations.
|
||||
645
skills/refactor/SKILL.md
Normal file
645
skills/refactor/SKILL.md
Normal file
@@ -0,0 +1,645 @@
|
||||
---
|
||||
name: refactor
|
||||
description: 'Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.'
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Refactor
|
||||
|
||||
## Overview
|
||||
|
||||
Improve code structure and readability without changing external behavior. Refactoring is gradual evolution, not revolution. Use this for improving existing code, not rewriting from scratch.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when:
|
||||
|
||||
- Code is hard to understand or maintain
|
||||
- Functions/classes are too large
|
||||
- Code smells need addressing
|
||||
- Adding features is difficult due to code structure
|
||||
- User asks "clean up this code", "refactor this", "improve this"
|
||||
|
||||
---
|
||||
|
||||
## Refactoring Principles
|
||||
|
||||
### The Golden Rules
|
||||
|
||||
1. **Behavior is preserved** - Refactoring doesn't change what the code does, only how
|
||||
2. **Small steps** - Make tiny changes, test after each
|
||||
3. **Version control is your friend** - Commit before and after each safe state
|
||||
4. **Tests are essential** - Without tests, you're not refactoring, you're editing
|
||||
5. **One thing at a time** - Don't mix refactoring with feature changes
|
||||
|
||||
### When NOT to Refactor
|
||||
|
||||
```
|
||||
- Code that works and won't change again (if it ain't broke...)
|
||||
- Critical production code without tests (add tests first)
|
||||
- When you're under a tight deadline
|
||||
- "Just because" - need a clear purpose
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Code Smells & Fixes
|
||||
|
||||
### 1. Long Method/Function
|
||||
|
||||
```diff
|
||||
# BAD: 200-line function that does everything
|
||||
- async function processOrder(orderId) {
|
||||
- // 50 lines: fetch order
|
||||
- // 30 lines: validate order
|
||||
- // 40 lines: calculate pricing
|
||||
- // 30 lines: update inventory
|
||||
- // 20 lines: create shipment
|
||||
- // 30 lines: send notifications
|
||||
- }
|
||||
|
||||
# GOOD: Broken into focused functions
|
||||
+ async function processOrder(orderId) {
|
||||
+ const order = await fetchOrder(orderId);
|
||||
+ validateOrder(order);
|
||||
+ const pricing = calculatePricing(order);
|
||||
+ await updateInventory(order);
|
||||
+ const shipment = await createShipment(order);
|
||||
+ await sendNotifications(order, pricing, shipment);
|
||||
+ return { order, pricing, shipment };
|
||||
+ }
|
||||
```
|
||||
|
||||
### 2. Duplicated Code
|
||||
|
||||
```diff
|
||||
# BAD: Same logic in multiple places
|
||||
- function calculateUserDiscount(user) {
|
||||
- if (user.membership === 'gold') return user.total * 0.2;
|
||||
- if (user.membership === 'silver') return user.total * 0.1;
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- function calculateOrderDiscount(order) {
|
||||
- if (order.user.membership === 'gold') return order.total * 0.2;
|
||||
- if (order.user.membership === 'silver') return order.total * 0.1;
|
||||
- return 0;
|
||||
- }
|
||||
|
||||
# GOOD: Extract common logic
|
||||
+ function getMembershipDiscountRate(membership) {
|
||||
+ const rates = { gold: 0.2, silver: 0.1 };
|
||||
+ return rates[membership] || 0;
|
||||
+ }
|
||||
+
|
||||
+ function calculateUserDiscount(user) {
|
||||
+ return user.total * getMembershipDiscountRate(user.membership);
|
||||
+ }
|
||||
+
|
||||
+ function calculateOrderDiscount(order) {
|
||||
+ return order.total * getMembershipDiscountRate(order.user.membership);
|
||||
+ }
|
||||
```
|
||||
|
||||
### 3. Large Class/Module
|
||||
|
||||
```diff
|
||||
# BAD: God object that knows too much
|
||||
- class UserManager {
|
||||
- createUser() { /* ... */ }
|
||||
- updateUser() { /* ... */ }
|
||||
- deleteUser() { /* ... */ }
|
||||
- sendEmail() { /* ... */ }
|
||||
- generateReport() { /* ... */ }
|
||||
- handlePayment() { /* ... */ }
|
||||
- validateAddress() { /* ... */ }
|
||||
- // 50 more methods...
|
||||
- }
|
||||
|
||||
# GOOD: Single responsibility per class
|
||||
+ class UserService {
|
||||
+ create(data) { /* ... */ }
|
||||
+ update(id, data) { /* ... */ }
|
||||
+ delete(id) { /* ... */ }
|
||||
+ }
|
||||
+
|
||||
+ class EmailService {
|
||||
+ send(to, subject, body) { /* ... */ }
|
||||
+ }
|
||||
+
|
||||
+ class ReportService {
|
||||
+ generate(type, params) { /* ... */ }
|
||||
+ }
|
||||
+
|
||||
+ class PaymentService {
|
||||
+ process(amount, method) { /* ... */ }
|
||||
+ }
|
||||
```
|
||||
|
||||
### 4. Long Parameter List
|
||||
|
||||
```diff
|
||||
# BAD: Too many parameters
|
||||
- function createUser(email, password, name, age, address, city, country, phone) {
|
||||
- /* ... */
|
||||
- }
|
||||
|
||||
# GOOD: Group related parameters
|
||||
+ interface UserData {
|
||||
+ email: string;
|
||||
+ password: string;
|
||||
+ name: string;
|
||||
+ age?: number;
|
||||
+ address?: Address;
|
||||
+ phone?: string;
|
||||
+ }
|
||||
+
|
||||
+ function createUser(data: UserData) {
|
||||
+ /* ... */
|
||||
+ }
|
||||
|
||||
# EVEN BETTER: Use builder pattern for complex construction
|
||||
+ const user = UserBuilder
|
||||
+ .email('test@example.com')
|
||||
+ .password('secure123')
|
||||
+ .name('Test User')
|
||||
+ .address(address)
|
||||
+ .build();
|
||||
```
|
||||
|
||||
### 5. Feature Envy
|
||||
|
||||
```diff
|
||||
# BAD: Method that uses another object's data more than its own
|
||||
- class Order {
|
||||
- calculateDiscount(user) {
|
||||
- if (user.membershipLevel === 'gold') {
|
||||
+ return this.total * 0.2;
|
||||
+ }
|
||||
+ if (user.accountAge > 365) {
|
||||
+ return this.total * 0.1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
# GOOD: Move logic to the object that owns the data
|
||||
+ class User {
|
||||
+ getDiscountRate(orderTotal) {
|
||||
+ if (this.membershipLevel === 'gold') return 0.2;
|
||||
+ if (this.accountAge > 365) return 0.1;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class Order {
|
||||
+ calculateDiscount(user) {
|
||||
+ return this.total * user.getDiscountRate(this.total);
|
||||
+ }
|
||||
+ }
|
||||
```
|
||||
|
||||
### 6. Primitive Obsession
|
||||
|
||||
```diff
|
||||
# BAD: Using primitives for domain concepts
|
||||
- function sendEmail(to, subject, body) { /* ... */ }
|
||||
- sendEmail('user@example.com', 'Hello', '...');
|
||||
|
||||
- function createPhone(country, number) {
|
||||
- return `${country}-${number}`;
|
||||
- }
|
||||
|
||||
# GOOD: Use domain types
|
||||
+ class Email {
|
||||
+ private constructor(public readonly value: string) {
|
||||
+ if (!Email.isValid(value)) throw new Error('Invalid email');
|
||||
+ }
|
||||
+ static create(value: string) { return new Email(value); }
|
||||
+ static isValid(email: string) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }
|
||||
+ }
|
||||
+
|
||||
+ class PhoneNumber {
|
||||
+ constructor(
|
||||
+ public readonly country: string,
|
||||
+ public readonly number: string
|
||||
+ ) {
|
||||
+ if (!PhoneNumber.isValid(country, number)) throw new Error('Invalid phone');
|
||||
+ }
|
||||
+ toString() { return `${this.country}-${this.number}`; }
|
||||
+ static isValid(country: string, number: string) { /* ... */ }
|
||||
+ }
|
||||
+
|
||||
+ // Usage
|
||||
+ const email = Email.create('user@example.com');
|
||||
+ const phone = new PhoneNumber('1', '555-1234');
|
||||
```
|
||||
|
||||
### 7. Magic Numbers/Strings
|
||||
|
||||
```diff
|
||||
# BAD: Unexplained values
|
||||
- if (user.status === 2) { /* ... */ }
|
||||
- const discount = total * 0.15;
|
||||
- setTimeout(callback, 86400000);
|
||||
|
||||
# GOOD: Named constants
|
||||
+ const UserStatus = {
|
||||
+ ACTIVE: 1,
|
||||
+ INACTIVE: 2,
|
||||
+ SUSPENDED: 3
|
||||
+ } as const;
|
||||
+
|
||||
+ const DISCOUNT_RATES = {
|
||||
+ STANDARD: 0.1,
|
||||
+ PREMIUM: 0.15,
|
||||
+ VIP: 0.2
|
||||
+ } as const;
|
||||
+
|
||||
+ const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
||||
+
|
||||
+ if (user.status === UserStatus.INACTIVE) { /* ... */ }
|
||||
+ const discount = total * DISCOUNT_RATES.PREMIUM;
|
||||
+ setTimeout(callback, ONE_DAY_MS);
|
||||
```
|
||||
|
||||
### 8. Nested Conditionals
|
||||
|
||||
```diff
|
||||
# BAD: Arrow code
|
||||
- function process(order) {
|
||||
- if (order) {
|
||||
- if (order.user) {
|
||||
- if (order.user.isActive) {
|
||||
- if (order.total > 0) {
|
||||
- return processOrder(order);
|
||||
+ } else {
|
||||
+ return { error: 'Invalid total' };
|
||||
+ }
|
||||
+ } else {
|
||||
+ return { error: 'User inactive' };
|
||||
+ }
|
||||
+ } else {
|
||||
+ return { error: 'No user' };
|
||||
+ }
|
||||
+ } else {
|
||||
+ return { error: 'No order' };
|
||||
+ }
|
||||
+ }
|
||||
|
||||
# GOOD: Guard clauses / early returns
|
||||
+ function process(order) {
|
||||
+ if (!order) return { error: 'No order' };
|
||||
+ if (!order.user) return { error: 'No user' };
|
||||
+ if (!order.user.isActive) return { error: 'User inactive' };
|
||||
+ if (order.total <= 0) return { error: 'Invalid total' };
|
||||
+ return processOrder(order);
|
||||
+ }
|
||||
|
||||
# EVEN BETER: Using Result type
|
||||
+ function process(order): Result<ProcessedOrder, Error> {
|
||||
+ return Result.combine([
|
||||
+ validateOrderExists(order),
|
||||
+ validateUserExists(order),
|
||||
+ validateUserActive(order.user),
|
||||
+ validateOrderTotal(order)
|
||||
+ ]).flatMap(() => processOrder(order));
|
||||
+ }
|
||||
```
|
||||
|
||||
### 9. Dead Code
|
||||
|
||||
```diff
|
||||
# BAD: Unused code lingers
|
||||
- function oldImplementation() { /* ... */ }
|
||||
- const DEPRECATED_VALUE = 5;
|
||||
- import { unusedThing } from './somewhere';
|
||||
- // Commented out code
|
||||
- // function oldCode() { /* ... */ }
|
||||
|
||||
# GOOD: Remove it
|
||||
+ // Delete unused functions, imports, and commented code
|
||||
+ // If you need it again, git history has it
|
||||
```
|
||||
|
||||
### 10. Inappropriate Intimacy
|
||||
|
||||
```diff
|
||||
# BAD: One class reaches deep into another
|
||||
- class OrderProcessor {
|
||||
- process(order) {
|
||||
- order.user.profile.address.street; // Too intimate
|
||||
- order.repository.connection.config; // Breaking encapsulation
|
||||
+ }
|
||||
+ }
|
||||
|
||||
# GOOD: Ask, don't tell
|
||||
+ class OrderProcessor {
|
||||
+ process(order) {
|
||||
+ order.getShippingAddress(); // Order knows how to get it
|
||||
+ order.save(); // Order knows how to save itself
|
||||
+ }
|
||||
+ }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Extract Method Refactoring
|
||||
|
||||
### Before and After
|
||||
|
||||
```diff
|
||||
# Before: One long function
|
||||
- function printReport(users) {
|
||||
- console.log('USER REPORT');
|
||||
- console.log('============');
|
||||
- console.log('');
|
||||
- console.log(`Total users: ${users.length}`);
|
||||
- console.log('');
|
||||
- console.log('ACTIVE USERS');
|
||||
- console.log('------------');
|
||||
- const active = users.filter(u => u.isActive);
|
||||
- active.forEach(u => {
|
||||
- console.log(`- ${u.name} (${u.email})`);
|
||||
- });
|
||||
- console.log('');
|
||||
- console.log(`Active: ${active.length}`);
|
||||
- console.log('');
|
||||
- console.log('INACTIVE USERS');
|
||||
- console.log('--------------');
|
||||
- const inactive = users.filter(u => !u.isActive);
|
||||
- inactive.forEach(u => {
|
||||
- console.log(`- ${u.name} (${u.email})`);
|
||||
- });
|
||||
- console.log('');
|
||||
- console.log(`Inactive: ${inactive.length}`);
|
||||
- }
|
||||
|
||||
# After: Extracted methods
|
||||
+ function printReport(users) {
|
||||
+ printHeader('USER REPORT');
|
||||
+ console.log(`Total users: ${users.length}\n`);
|
||||
+ printUserSection('ACTIVE USERS', users.filter(u => u.isActive));
|
||||
+ printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));
|
||||
+ }
|
||||
+
|
||||
+ function printHeader(title) {
|
||||
+ const line = '='.repeat(title.length);
|
||||
+ console.log(title);
|
||||
+ console.log(line);
|
||||
+ console.log('');
|
||||
+ }
|
||||
+
|
||||
+ function printUserSection(title, users) {
|
||||
+ console.log(title);
|
||||
+ console.log('-'.repeat(title.length));
|
||||
+ users.forEach(u => console.log(`- ${u.name} (${u.email})`));
|
||||
+ console.log('');
|
||||
+ console.log(`${title.split(' ')[0]}: ${users.length}`);
|
||||
+ console.log('');
|
||||
+ }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Introducing Type Safety
|
||||
|
||||
### From Untyped to Typed
|
||||
|
||||
```diff
|
||||
# Before: No types
|
||||
- function calculateDiscount(user, total, membership, date) {
|
||||
- if (membership === 'gold' && date.getDay() === 5) {
|
||||
- return total * 0.25;
|
||||
- }
|
||||
- if (membership === 'gold') return total * 0.2;
|
||||
- return total * 0.1;
|
||||
- }
|
||||
|
||||
# After: Full type safety
|
||||
+ type Membership = 'bronze' | 'silver' | 'gold';
|
||||
+
|
||||
+ interface User {
|
||||
+ id: string;
|
||||
+ name: string;
|
||||
+ membership: Membership;
|
||||
+ }
|
||||
+
|
||||
+ interface DiscountResult {
|
||||
+ original: number;
|
||||
+ discount: number;
|
||||
+ final: number;
|
||||
+ rate: number;
|
||||
+ }
|
||||
+
|
||||
+ function calculateDiscount(
|
||||
+ user: User,
|
||||
+ total: number,
|
||||
+ date: Date = new Date()
|
||||
+ ): DiscountResult {
|
||||
+ if (total < 0) throw new Error('Total cannot be negative');
|
||||
+
|
||||
+ let rate = 0.1; // Default bronze
|
||||
+
|
||||
+ if (user.membership === 'gold' && date.getDay() === 5) {
|
||||
+ rate = 0.25; // Friday bonus for gold
|
||||
+ } else if (user.membership === 'gold') {
|
||||
+ rate = 0.2;
|
||||
+ } else if (user.membership === 'silver') {
|
||||
+ rate = 0.15;
|
||||
+ }
|
||||
+
|
||||
+ const discount = total * rate;
|
||||
+
|
||||
+ return {
|
||||
+ original: total,
|
||||
+ discount,
|
||||
+ final: total - discount,
|
||||
+ rate
|
||||
+ };
|
||||
+ }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Design Patterns for Refactoring
|
||||
|
||||
### Strategy Pattern
|
||||
|
||||
```diff
|
||||
# Before: Conditional logic
|
||||
- function calculateShipping(order, method) {
|
||||
- if (method === 'standard') {
|
||||
- return order.total > 50 ? 0 : 5.99;
|
||||
- } else if (method === 'express') {
|
||||
- return order.total > 100 ? 9.99 : 14.99;
|
||||
+ } else if (method === 'overnight') {
|
||||
+ return 29.99;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
# After: Strategy pattern
|
||||
+ interface ShippingStrategy {
|
||||
+ calculate(order: Order): number;
|
||||
+ }
|
||||
+
|
||||
+ class StandardShipping implements ShippingStrategy {
|
||||
+ calculate(order: Order) {
|
||||
+ return order.total > 50 ? 0 : 5.99;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class ExpressShipping implements ShippingStrategy {
|
||||
+ calculate(order: Order) {
|
||||
+ return order.total > 100 ? 9.99 : 14.99;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class OvernightShipping implements ShippingStrategy {
|
||||
+ calculate(order: Order) {
|
||||
+ return 29.99;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ function calculateShipping(order: Order, strategy: ShippingStrategy) {
|
||||
+ return strategy.calculate(order);
|
||||
+ }
|
||||
```
|
||||
|
||||
### Chain of Responsibility
|
||||
|
||||
```diff
|
||||
# Before: Nested validation
|
||||
- function validate(user) {
|
||||
- const errors = [];
|
||||
- if (!user.email) errors.push('Email required');
|
||||
+ else if (!isValidEmail(user.email)) errors.push('Invalid email');
|
||||
+ if (!user.name) errors.push('Name required');
|
||||
+ if (user.age < 18) errors.push('Must be 18+');
|
||||
+ if (user.country === 'blocked') errors.push('Country not supported');
|
||||
+ return errors;
|
||||
+ }
|
||||
|
||||
# After: Chain of responsibility
|
||||
+ abstract class Validator {
|
||||
+ abstract validate(user: User): string | null;
|
||||
+ setNext(validator: Validator): Validator {
|
||||
+ this.next = validator;
|
||||
+ return validator;
|
||||
+ }
|
||||
+ validate(user: User): string | null {
|
||||
+ const error = this.doValidate(user);
|
||||
+ if (error) return error;
|
||||
+ return this.next?.validate(user) ?? null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class EmailRequiredValidator extends Validator {
|
||||
+ doValidate(user: User) {
|
||||
+ return !user.email ? 'Email required' : null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ class EmailFormatValidator extends Validator {
|
||||
+ doValidate(user: User) {
|
||||
+ return user.email && !isValidEmail(user.email) ? 'Invalid email' : null;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Build the chain
|
||||
+ const validator = new EmailRequiredValidator()
|
||||
+ .setNext(new EmailFormatValidator())
|
||||
+ .setNext(new NameRequiredValidator())
|
||||
+ .setNext(new AgeValidator())
|
||||
+ .setNext(new CountryValidator());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Refactoring Steps
|
||||
|
||||
### Safe Refactoring Process
|
||||
|
||||
```
|
||||
1. PREPARE
|
||||
- Ensure tests exist (write them if missing)
|
||||
- Commit current state
|
||||
- Create feature branch
|
||||
|
||||
2. IDENTIFY
|
||||
- Find the code smell to address
|
||||
- Understand what the code does
|
||||
- Plan the refactoring
|
||||
|
||||
3. REFACTOR (small steps)
|
||||
- Make one small change
|
||||
- Run tests
|
||||
- Commit if tests pass
|
||||
- Repeat
|
||||
|
||||
4. VERIFY
|
||||
- All tests pass
|
||||
- Manual testing if needed
|
||||
- Performance unchanged or improved
|
||||
|
||||
5. CLEAN UP
|
||||
- Update comments
|
||||
- Update documentation
|
||||
- Final commit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Refactoring Checklist
|
||||
|
||||
### Code Quality
|
||||
|
||||
- [ ] Functions are small (< 50 lines)
|
||||
- [ ] Functions do one thing
|
||||
- [ ] No duplicated code
|
||||
- [ ] Descriptive names (variables, functions, classes)
|
||||
- [ ] No magic numbers/strings
|
||||
- [ ] Dead code removed
|
||||
|
||||
### Structure
|
||||
|
||||
- [ ] Related code is together
|
||||
- [ ] Clear module boundaries
|
||||
- [ ] Dependencies flow in one direction
|
||||
- [ ] No circular dependencies
|
||||
|
||||
### Type Safety
|
||||
|
||||
- [ ] Types defined for all public APIs
|
||||
- [ ] No `any` types without justification
|
||||
- [ ] Nullable types explicitly marked
|
||||
|
||||
### Testing
|
||||
|
||||
- [ ] Refactored code is tested
|
||||
- [ ] Tests cover edge cases
|
||||
- [ ] All tests pass
|
||||
|
||||
---
|
||||
|
||||
## Common Refactoring Operations
|
||||
|
||||
| Operation | Description |
|
||||
| --------------------------------------------- | ------------------------------------- |
|
||||
| Extract Method | Turn code fragment into method |
|
||||
| Extract Class | Move behavior to new class |
|
||||
| Extract Interface | Create interface from implementation |
|
||||
| Inline Method | Move method body back to caller |
|
||||
| Inline Class | Move class behavior to caller |
|
||||
| Pull Up Method | Move method to superclass |
|
||||
| Push Down Method | Move method to subclass |
|
||||
| Rename Method/Variable | Improve clarity |
|
||||
| Introduce Parameter Object | Group related parameters |
|
||||
| Replace Conditional with Polymorphism | Use polymorphism instead of switch/if |
|
||||
| Replace Magic Number with Constant | Named constants |
|
||||
| Decompose Conditional | Break complex conditions |
|
||||
| Consolidate Conditional | Combine duplicate conditions |
|
||||
| Replace Nested Conditional with Guard Clauses | Early returns |
|
||||
| Introduce Null Object | Eliminate null checks |
|
||||
| Replace Type Code with Class/Enum | Strong typing |
|
||||
| Replace Inheritance with Delegation | Composition over inheritance |
|
||||
Reference in New Issue
Block a user