@ranimontagna/agent-toolkit 0.1.7 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -14
- package/dist/src/args.js +10 -0
- package/dist/src/args.js.map +1 -1
- package/dist/src/menu.js +43 -2
- package/dist/src/menu.js.map +1 -1
- package/dist/src/skills.js +9 -2
- package/dist/src/skills.js.map +1 -1
- package/dist/src/state.d.ts +2 -0
- package/dist/src/state.js +7 -0
- package/dist/src/state.js.map +1 -1
- package/dist/src/status.js +3 -1
- package/dist/src/status.js.map +1 -1
- package/dist/src/ui.js +4 -1
- package/dist/src/ui.js.map +1 -1
- package/dist/src/usage.js +2 -0
- package/dist/src/usage.js.map +1 -1
- package/docs/assets/install-plan.svg +2 -2
- package/docs/assets/install-skill-packages.svg +14 -14
- package/package.json +1 -1
- package/skills/backend/database/postgres-patterns/LICENSE.ANTIGRAVITY +21 -0
- package/skills/backend/database/postgres-patterns/LICENSE.ECC +21 -0
- package/skills/backend/database/postgres-patterns/NOTICE.md +11 -0
- package/skills/backend/database/postgres-patterns/SKILL.md +180 -0
- package/skills/backend/kotlin/kotlin-patterns/LICENSE +21 -0
- package/skills/backend/kotlin/kotlin-patterns/NOTICE.md +7 -0
- package/skills/backend/kotlin/kotlin-patterns/SKILL.md +711 -0
- package/skills/backend/kotlin/kotlin-testing/LICENSE +21 -0
- package/skills/backend/kotlin/kotlin-testing/NOTICE.md +7 -0
- package/skills/backend/kotlin/kotlin-testing/SKILL.md +824 -0
- package/skills/backend/python/python-patterns/LICENSE +21 -0
- package/skills/backend/python/python-patterns/NOTICE.md +7 -0
- package/skills/backend/python/python-patterns/SKILL.md +424 -0
- package/skills/backend/python/python-testing/LICENSE +21 -0
- package/skills/backend/python/python-testing/NOTICE.md +7 -0
- package/skills/backend/python/python-testing/SKILL.md +494 -0
- package/skills/devops/docker-patterns/LICENSE.ANTIGRAVITY +21 -0
- package/skills/devops/docker-patterns/LICENSE.ECC +21 -0
- package/skills/devops/docker-patterns/NOTICE.md +11 -0
- package/skills/devops/docker-patterns/SKILL.md +397 -0
- package/skills/frontend/accessibility/LICENSE +21 -0
- package/skills/frontend/accessibility/NOTICE.md +10 -0
- package/skills/frontend/accessibility/SKILL.md +145 -0
- package/skills/frontend/design/ui-ux-pro-max/LICENSE +21 -0
- package/skills/frontend/design/ui-ux-pro-max/NOTICE.md +12 -0
- package/skills/frontend/design/ui-ux-pro-max/SKILL.md +672 -0
- package/skills/frontend/design/ui-ux-pro-max/data/_sync_all.py +414 -0
- package/skills/frontend/design/ui-ux-pro-max/data/app-interface.csv +31 -0
- package/skills/frontend/design/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/frontend/design/ui-ux-pro-max/data/colors.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/design.csv +1776 -0
- package/skills/frontend/design/ui-ux-pro-max/data/draft.csv +1779 -0
- package/skills/frontend/design/ui-ux-pro-max/data/google-fonts.csv +1924 -0
- package/skills/frontend/design/ui-ux-pro-max/data/icons.csv +106 -0
- package/skills/frontend/design/ui-ux-pro-max/data/landing.csv +35 -0
- package/skills/frontend/design/ui-ux-pro-max/data/products.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/angular.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/laravel.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/threejs.csv +54 -0
- package/skills/frontend/design/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/frontend/design/ui-ux-pro-max/data/styles.csv +85 -0
- package/skills/frontend/design/ui-ux-pro-max/data/typography.csv +74 -0
- package/skills/frontend/design/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
- package/skills/frontend/design/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/core.py +262 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/design_system.py +1148 -0
- package/skills/frontend/design/ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/general/code-reviewer/AGENTS.md +292 -0
- package/skills/general/code-reviewer/LICENSE +201 -0
- package/skills/general/code-reviewer/NOTICE.md +10 -0
- package/skills/general/code-reviewer/SKILL.md +132 -0
- package/skills/general/code-reviewer/rules/correctness-error-handling.md +279 -0
- package/skills/general/code-reviewer/rules/maintainability-naming.md +149 -0
- package/skills/general/code-reviewer/rules/maintainability-type-hints.md +93 -0
- package/skills/general/code-reviewer/rules/performance-n-plus-one.md +250 -0
- package/skills/general/code-reviewer/rules/security-sql-injection.md +142 -0
- package/skills/general/code-reviewer/rules/security-xss-prevention.md +225 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-reviewer
|
|
3
|
+
description: Use when reviewing code, pull requests, security vulnerabilities, performance issues, correctness risks, maintainability problems, or pre-deployment quality.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
metadata:
|
|
6
|
+
author: awesome-llm-apps
|
|
7
|
+
version: "2.0.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Code Reviewer
|
|
11
|
+
|
|
12
|
+
You are an expert code reviewer who identifies security vulnerabilities, performance issues, and code quality problems.
|
|
13
|
+
|
|
14
|
+
## When to Apply
|
|
15
|
+
|
|
16
|
+
Use this skill when:
|
|
17
|
+
- Reviewing pull requests
|
|
18
|
+
- Performing security audits
|
|
19
|
+
- Checking code quality
|
|
20
|
+
- Identifying performance bottlenecks
|
|
21
|
+
- Ensuring best practices
|
|
22
|
+
- Pre-deployment code review
|
|
23
|
+
|
|
24
|
+
## How to Use This Skill
|
|
25
|
+
|
|
26
|
+
This skill contains **detailed rules** in the `rules/` directory, organized by category and priority.
|
|
27
|
+
|
|
28
|
+
### Quick Start
|
|
29
|
+
|
|
30
|
+
1. **Review [AGENTS.md](AGENTS.md)** for a complete compilation of all rules with examples
|
|
31
|
+
2. **Reference specific rules** from `rules/` directory for deep dives
|
|
32
|
+
3. **Follow priority order**: Security → Performance → Correctness → Maintainability
|
|
33
|
+
|
|
34
|
+
### Available Rules
|
|
35
|
+
|
|
36
|
+
**Security (CRITICAL)**
|
|
37
|
+
- [SQL Injection Prevention](rules/security-sql-injection.md)
|
|
38
|
+
- [XSS Prevention](rules/security-xss-prevention.md)
|
|
39
|
+
|
|
40
|
+
**Performance (HIGH)**
|
|
41
|
+
- [Avoid N+1 Query Problem](rules/performance-n-plus-one.md)
|
|
42
|
+
|
|
43
|
+
**Correctness (HIGH)**
|
|
44
|
+
- [Proper Error Handling](rules/correctness-error-handling.md)
|
|
45
|
+
|
|
46
|
+
**Maintainability (MEDIUM)**
|
|
47
|
+
- [Use Meaningful Variable Names](rules/maintainability-naming.md)
|
|
48
|
+
- [Add Type Hints](rules/maintainability-type-hints.md)
|
|
49
|
+
|
|
50
|
+
## Review Process
|
|
51
|
+
|
|
52
|
+
### 1. **Security First** (CRITICAL)
|
|
53
|
+
Look for vulnerabilities that could lead to data breaches or unauthorized access:
|
|
54
|
+
- SQL injection
|
|
55
|
+
- XSS (Cross-Site Scripting)
|
|
56
|
+
- Authentication/authorization bypasses
|
|
57
|
+
- Hardcoded secrets
|
|
58
|
+
- Insecure dependencies
|
|
59
|
+
|
|
60
|
+
### 2. **Performance** (HIGH)
|
|
61
|
+
Identify code that will cause slow performance at scale:
|
|
62
|
+
- N+1 database queries
|
|
63
|
+
- Missing indexes
|
|
64
|
+
- Inefficient algorithms
|
|
65
|
+
- Memory leaks
|
|
66
|
+
- Unnecessary API calls
|
|
67
|
+
|
|
68
|
+
### 3. **Correctness** (HIGH)
|
|
69
|
+
Find bugs and edge cases:
|
|
70
|
+
- Error handling gaps
|
|
71
|
+
- Race conditions
|
|
72
|
+
- Off-by-one errors
|
|
73
|
+
- Null/undefined handling
|
|
74
|
+
- Input validation
|
|
75
|
+
|
|
76
|
+
### 4. **Maintainability** (MEDIUM)
|
|
77
|
+
Improve code quality for long-term health:
|
|
78
|
+
- Clear naming
|
|
79
|
+
- Type safety
|
|
80
|
+
- DRY principle
|
|
81
|
+
- Single responsibility
|
|
82
|
+
- Documentation
|
|
83
|
+
|
|
84
|
+
### 5. **Testing**
|
|
85
|
+
Verify adequate coverage:
|
|
86
|
+
- Unit tests for new code
|
|
87
|
+
- Edge case testing
|
|
88
|
+
- Error path testing
|
|
89
|
+
- Integration tests where needed
|
|
90
|
+
|
|
91
|
+
## Review Output Format
|
|
92
|
+
|
|
93
|
+
Structure your reviews as:
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
This function retrieves user data but has critical security and reliability issues.
|
|
97
|
+
|
|
98
|
+
## Critical Issues 🔴
|
|
99
|
+
|
|
100
|
+
1. **SQL Injection Vulnerability** (Line 2)
|
|
101
|
+
- **Problem:** User input directly interpolated into SQL query
|
|
102
|
+
- **Impact:** Attackers can execute arbitrary SQL commands
|
|
103
|
+
- **Fix:** Use parameterized queries
|
|
104
|
+
```python
|
|
105
|
+
query = "SELECT * FROM users WHERE id = ?"
|
|
106
|
+
result = db.execute(query, (user_id,))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## High Priority 🟠
|
|
110
|
+
|
|
111
|
+
1. **No Error Handling** (Line 3-4)
|
|
112
|
+
- **Problem:** Assumes result always has data
|
|
113
|
+
- **Impact:** IndexError if user doesn't exist
|
|
114
|
+
- **Fix:** Check result before accessing
|
|
115
|
+
```python
|
|
116
|
+
if not result:
|
|
117
|
+
return None
|
|
118
|
+
return result[0]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
2. **Missing Type Hints** (Line 1)
|
|
122
|
+
- **Problem:** No type annotations
|
|
123
|
+
- **Impact:** Reduces code clarity and IDE support
|
|
124
|
+
- **Fix:** Add type hints
|
|
125
|
+
```python
|
|
126
|
+
def get_user(user_id: int) -> Optional[Dict[str, Any]]:
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Recommendations
|
|
130
|
+
- Add logging for debugging
|
|
131
|
+
- Consider using an ORM to prevent SQL injection
|
|
132
|
+
- Add input validation for user_id
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Proper Error Handling
|
|
3
|
+
impact: HIGH
|
|
4
|
+
category: correctness
|
|
5
|
+
tags: errors, exceptions, reliability
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Proper Error Handling
|
|
9
|
+
|
|
10
|
+
Always handle errors explicitly. Don't use bare except clauses or ignore errors silently. Provide helpful error messages.
|
|
11
|
+
|
|
12
|
+
## Why This Matters
|
|
13
|
+
|
|
14
|
+
Proper error handling:
|
|
15
|
+
- Prevents silent failures
|
|
16
|
+
- Aids debugging with clear messages
|
|
17
|
+
- Allows graceful degradation
|
|
18
|
+
- Improves user experience
|
|
19
|
+
- Enables error monitoring/alerting
|
|
20
|
+
|
|
21
|
+
## ❌ Incorrect
|
|
22
|
+
|
|
23
|
+
### Bare Except Clause
|
|
24
|
+
```python
|
|
25
|
+
# ❌ Catches everything, including KeyboardInterrupt, SystemExit
|
|
26
|
+
try:
|
|
27
|
+
result = risky_operation()
|
|
28
|
+
except:
|
|
29
|
+
pass # Silent failure, no idea what went wrong
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Generic Exception Without Context
|
|
33
|
+
```python
|
|
34
|
+
# ❌ Too generic, loses error information
|
|
35
|
+
try:
|
|
36
|
+
data = fetch_user(user_id)
|
|
37
|
+
process(data)
|
|
38
|
+
save_result()
|
|
39
|
+
except Exception:
|
|
40
|
+
print("Error occurred") # Which operation failed? Why?
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Ignoring Specific Errors
|
|
44
|
+
```python
|
|
45
|
+
# ❌ Ignoring errors entirely
|
|
46
|
+
try:
|
|
47
|
+
config = json.loads(config_file.read())
|
|
48
|
+
except json.JSONDecodeError:
|
|
49
|
+
pass # App continues with undefined 'config'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## ✅ Correct
|
|
53
|
+
|
|
54
|
+
### Catch Specific Exceptions
|
|
55
|
+
```python
|
|
56
|
+
# ✅ Handle specific errors appropriately
|
|
57
|
+
try:
|
|
58
|
+
config = json.loads(config_file.read())
|
|
59
|
+
except json.JSONDecodeError as e:
|
|
60
|
+
logger.error(f"Invalid JSON in config file: {e}")
|
|
61
|
+
# Provide sensible default
|
|
62
|
+
config = get_default_config()
|
|
63
|
+
except FileNotFoundError:
|
|
64
|
+
logger.warning("Config file not found, using defaults")
|
|
65
|
+
config = get_default_config()
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Provide Context in Error Messages
|
|
69
|
+
```python
|
|
70
|
+
# ✅ Clear, actionable error messages
|
|
71
|
+
def get_user(user_id: int) -> User:
|
|
72
|
+
try:
|
|
73
|
+
response = requests.get(f"{API_URL}/users/{user_id}", timeout=5)
|
|
74
|
+
response.raise_for_status()
|
|
75
|
+
return User(**response.json())
|
|
76
|
+
except requests.Timeout:
|
|
77
|
+
raise ValueError(
|
|
78
|
+
f"Timeout fetching user {user_id} from {API_URL}. "
|
|
79
|
+
"Check network connection or increase timeout."
|
|
80
|
+
)
|
|
81
|
+
except requests.HTTPError as e:
|
|
82
|
+
if e.response.status_code == 404:
|
|
83
|
+
raise UserNotFoundError(f"User {user_id} does not exist")
|
|
84
|
+
raise ValueError(f"HTTP error fetching user {user_id}: {e}")
|
|
85
|
+
except json.JSONDecodeError:
|
|
86
|
+
raise ValueError(f"Invalid JSON response for user {user_id}")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Re-raise with Context
|
|
90
|
+
```python
|
|
91
|
+
# ✅ Add context while preserving stack trace
|
|
92
|
+
try:
|
|
93
|
+
process_batch(items)
|
|
94
|
+
except ValidationError as e:
|
|
95
|
+
# Add context and re-raise
|
|
96
|
+
raise ValidationError(
|
|
97
|
+
f"Batch processing failed for {len(items)} items: {e}"
|
|
98
|
+
) from e
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## JavaScript/TypeScript
|
|
102
|
+
|
|
103
|
+
### ❌ Catching Without Specificity
|
|
104
|
+
```javascript
|
|
105
|
+
// ❌ No error handling
|
|
106
|
+
async function fetchUser(id) {
|
|
107
|
+
const response = await fetch(`/api/users/${id}`);
|
|
108
|
+
return response.json(); // What if fetch fails? What if not JSON?
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ❌ Generic catch
|
|
112
|
+
try {
|
|
113
|
+
const user = await fetchUser(id);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.log('Error'); // Which error? From where?
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### ✅ Explicit Error Handling
|
|
120
|
+
```typescript
|
|
121
|
+
// ✅ Proper error handling with types
|
|
122
|
+
class UserNotFoundError extends Error {
|
|
123
|
+
constructor(userId: string) {
|
|
124
|
+
super(`User ${userId} not found`);
|
|
125
|
+
this.name = 'UserNotFoundError';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function fetchUser(id: string): Promise<User> {
|
|
130
|
+
let response: Response;
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
response = await fetch(`/api/users/${id}`, {
|
|
134
|
+
signal: AbortSignal.timeout(5000)
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error instanceof DOMException && error.name === 'TimeoutError') {
|
|
138
|
+
throw new Error(`Timeout fetching user ${id}`);
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`Network error fetching user ${id}: ${error}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!response.ok) {
|
|
144
|
+
if (response.status === 404) {
|
|
145
|
+
throw new UserNotFoundError(id);
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`HTTP ${response.status} fetching user ${id}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
return await response.json();
|
|
152
|
+
} catch (error) {
|
|
153
|
+
throw new Error(`Invalid JSON response for user ${id}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Usage
|
|
158
|
+
try {
|
|
159
|
+
const user = await fetchUser(userId);
|
|
160
|
+
displayUser(user);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (error instanceof UserNotFoundError) {
|
|
163
|
+
showNotFoundMessage();
|
|
164
|
+
} else {
|
|
165
|
+
logger.error('Failed to load user:', error);
|
|
166
|
+
showErrorMessage('Unable to load user. Please try again.');
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Error Handling Patterns
|
|
172
|
+
|
|
173
|
+
### Result Type (Rust-inspired)
|
|
174
|
+
```typescript
|
|
175
|
+
type Result<T, E = Error> =
|
|
176
|
+
| { ok: true; value: T }
|
|
177
|
+
| { ok: false; error: E };
|
|
178
|
+
|
|
179
|
+
function parseConfig(json: string): Result<Config> {
|
|
180
|
+
try {
|
|
181
|
+
const config = JSON.parse(json);
|
|
182
|
+
return { ok: true, value: config };
|
|
183
|
+
} catch (error) {
|
|
184
|
+
return { ok: false, error: new Error(`Invalid config: ${error}`) };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Usage
|
|
189
|
+
const result = parseConfig(configString);
|
|
190
|
+
if (result.ok) {
|
|
191
|
+
useConfig(result.value);
|
|
192
|
+
} else {
|
|
193
|
+
logger.error(result.error);
|
|
194
|
+
useDefaultConfig();
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Custom Error Classes
|
|
199
|
+
```python
|
|
200
|
+
class DatabaseError(Exception):
|
|
201
|
+
"""Base class for database errors."""
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
class ConnectionError(DatabaseError):
|
|
205
|
+
"""Database connection failed."""
|
|
206
|
+
pass
|
|
207
|
+
|
|
208
|
+
class QueryError(DatabaseError):
|
|
209
|
+
"""Query execution failed."""
|
|
210
|
+
def __init__(self, query: str, original_error: Exception):
|
|
211
|
+
self.query = query
|
|
212
|
+
self.original_error = original_error
|
|
213
|
+
super().__init__(f"Query failed: {query[:100]}... Error: {original_error}")
|
|
214
|
+
|
|
215
|
+
# Usage
|
|
216
|
+
try:
|
|
217
|
+
db.execute(query)
|
|
218
|
+
except psycopg2.OperationalError as e:
|
|
219
|
+
raise ConnectionError(f"Cannot connect to database: {e}") from e
|
|
220
|
+
except psycopg2.Error as e:
|
|
221
|
+
raise QueryError(query, e) from e
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Logging Errors
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
import logging
|
|
228
|
+
|
|
229
|
+
logger = logging.getLogger(__name__)
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
result = complex_operation()
|
|
233
|
+
except ValueError as e:
|
|
234
|
+
logger.error(
|
|
235
|
+
"Operation failed",
|
|
236
|
+
exc_info=True, # Include stack trace
|
|
237
|
+
extra={
|
|
238
|
+
'user_id': user_id,
|
|
239
|
+
'operation': 'complex_operation',
|
|
240
|
+
'input_data': sanitized_data
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
raise
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Best Practices
|
|
247
|
+
|
|
248
|
+
- [ ] **Catch specific exceptions** (not bare `except` or generic `Exception`)
|
|
249
|
+
- [ ] **Provide context** in error messages (what failed, why, how to fix)
|
|
250
|
+
- [ ] **Log errors** with relevant details
|
|
251
|
+
- [ ] **Don't silently ignore errors**
|
|
252
|
+
- [ ] **Use custom exception classes** for domain errors
|
|
253
|
+
- [ ] **Include stack traces** in logs (but not user-facing messages)
|
|
254
|
+
- [ ] **Handle errors at appropriate level** (don't catch too early)
|
|
255
|
+
- [ ] **Clean up resources** (use context managers/try-finally)
|
|
256
|
+
|
|
257
|
+
## Monitoring & Alerting
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
# Integration with error tracking
|
|
261
|
+
import sentry_sdk
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
process_payment(order)
|
|
265
|
+
except PaymentError as e:
|
|
266
|
+
sentry_sdk.capture_exception(e)
|
|
267
|
+
sentry_sdk.set_context("order", {
|
|
268
|
+
"order_id": order.id,
|
|
269
|
+
"amount": order.total,
|
|
270
|
+
"user_id": order.user_id
|
|
271
|
+
})
|
|
272
|
+
raise
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## References
|
|
276
|
+
|
|
277
|
+
- [Python Exception Handling Best Practices](https://docs.python.org/3/tutorial/errors.html)
|
|
278
|
+
- [Error Handling in JavaScript](https://javascript.info/try-catch)
|
|
279
|
+
- [Sentry Error Monitoring](https://sentry.io/)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Meaningful Variable Names
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
category: maintainability
|
|
5
|
+
tags: naming, readability, code-quality
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Use Meaningful Variable Names
|
|
9
|
+
|
|
10
|
+
Choose descriptive, intention-revealing names. Avoid single letters (except loop counters), abbreviations, and generic names.
|
|
11
|
+
|
|
12
|
+
## Why This Matters
|
|
13
|
+
|
|
14
|
+
Code is read 10x more than it's written. Clear names:
|
|
15
|
+
- Make code self-documenting
|
|
16
|
+
- Reduce cognitive load
|
|
17
|
+
- Prevent bugs from misunderstanding
|
|
18
|
+
- Enable easier refactoring
|
|
19
|
+
|
|
20
|
+
## ❌ Incorrect
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
# ❌ Cryptic, meaningless
|
|
24
|
+
def calc(x, y, z):
|
|
25
|
+
tmp = x * y
|
|
26
|
+
res = tmp + z
|
|
27
|
+
return res
|
|
28
|
+
|
|
29
|
+
# ❌ Too generic
|
|
30
|
+
data = fetch_data()
|
|
31
|
+
result = process(data)
|
|
32
|
+
output = format(result)
|
|
33
|
+
|
|
34
|
+
# ❌ Confusing abbreviations
|
|
35
|
+
usr_nm = input()
|
|
36
|
+
acc_bal = get_bal(usr_nm)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ✅ Correct
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
# ✅ Clear, descriptive
|
|
43
|
+
def calculate_total_price(item_price: float, quantity: int, tax_rate: float) -> float:
|
|
44
|
+
"""Calculate total price including tax."""
|
|
45
|
+
subtotal = item_price * quantity
|
|
46
|
+
total_with_tax = subtotal + (subtotal * tax_rate)
|
|
47
|
+
return total_with_tax
|
|
48
|
+
|
|
49
|
+
# ✅ Intention-revealing
|
|
50
|
+
customer_orders = fetch_customer_orders(customer_id)
|
|
51
|
+
validated_orders = validate_orders(customer_orders)
|
|
52
|
+
order_confirmation_email = format_confirmation_email(validated_orders)
|
|
53
|
+
|
|
54
|
+
# ✅ Full words
|
|
55
|
+
username = input("Enter username: ")
|
|
56
|
+
account_balance = get_account_balance(username)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Naming Conventions by Language
|
|
60
|
+
|
|
61
|
+
### Python (PEP 8)
|
|
62
|
+
```python
|
|
63
|
+
# Variables & functions: snake_case
|
|
64
|
+
user_count = 10
|
|
65
|
+
def calculate_average(): pass
|
|
66
|
+
|
|
67
|
+
# Classes: PascalCase
|
|
68
|
+
class UserAccount: pass
|
|
69
|
+
|
|
70
|
+
# Constants: UPPER_SNAKE_CASE
|
|
71
|
+
MAX_RETRY_ATTEMPTS = 3
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### JavaScript/TypeScript
|
|
75
|
+
```javascript
|
|
76
|
+
// Variables & functions: camelCase
|
|
77
|
+
const userCount = 10;
|
|
78
|
+
function calculateAverage() {}
|
|
79
|
+
|
|
80
|
+
// Classes: PascalCase
|
|
81
|
+
class UserAccount {}
|
|
82
|
+
|
|
83
|
+
// Constants: UPPER_SNAKE_CASE or camelCase
|
|
84
|
+
const MAX_RETRY_ATTEMPTS = 3;
|
|
85
|
+
const maxRetryAttempts = 3; // Also acceptable
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Booleans
|
|
89
|
+
```python
|
|
90
|
+
# Use is_, has_, can_ prefixes
|
|
91
|
+
is_active = True
|
|
92
|
+
has_permission = check_permission()
|
|
93
|
+
can_edit = user.role == "admin"
|
|
94
|
+
|
|
95
|
+
# Not: active, permission, editable
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Context Matters
|
|
99
|
+
|
|
100
|
+
### Loop Variables
|
|
101
|
+
```python
|
|
102
|
+
# ❌ Generic in complex loop
|
|
103
|
+
for i in users:
|
|
104
|
+
for j in i.orders:
|
|
105
|
+
process(j)
|
|
106
|
+
|
|
107
|
+
# ✅ Descriptive
|
|
108
|
+
for user in users:
|
|
109
|
+
for order in user.orders:
|
|
110
|
+
process_order(order)
|
|
111
|
+
|
|
112
|
+
# ✅ Single letter OK for simple index
|
|
113
|
+
for i in range(10):
|
|
114
|
+
print(i)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Scope-Appropriate Names
|
|
118
|
+
```python
|
|
119
|
+
# Short scope: concise OK
|
|
120
|
+
def validate(email):
|
|
121
|
+
# 'email' is clear in this small function
|
|
122
|
+
return '@' in email and '.' in email
|
|
123
|
+
|
|
124
|
+
# Long scope: more descriptive
|
|
125
|
+
class UserAuthenticationService:
|
|
126
|
+
def __init__(self):
|
|
127
|
+
# Longer, clearer for class-level
|
|
128
|
+
self.failed_login_attempts = {}
|
|
129
|
+
self.account_lockout_duration_seconds = 300
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Avoid Ambiguity
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# ❌ Ambiguous
|
|
136
|
+
def get_data(id):
|
|
137
|
+
return data[id]
|
|
138
|
+
|
|
139
|
+
# What data? What ID?
|
|
140
|
+
|
|
141
|
+
# ✅ Specific
|
|
142
|
+
def get_user_by_id(user_id: int) -> User:
|
|
143
|
+
return users_cache[user_id]
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## References
|
|
147
|
+
|
|
148
|
+
- [PEP 8 - Python Naming Conventions](https://peps.python.org/pep-0008/#naming-conventions)
|
|
149
|
+
- [Clean Code by Robert Martin](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Add Type Hints
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
category: maintainability
|
|
5
|
+
tags: types, python, typescript, type-safety
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Add Type Hints
|
|
9
|
+
|
|
10
|
+
Use type annotations to make code self-documenting and catch errors early.
|
|
11
|
+
|
|
12
|
+
## Why This Matters
|
|
13
|
+
|
|
14
|
+
Type hints provide:
|
|
15
|
+
- **Static analysis** - catch bugs before runtime
|
|
16
|
+
- **Better IDE support** - autocomplete, refactoring
|
|
17
|
+
- **Documentation** - types explain intent
|
|
18
|
+
- **Confidence** - easier refactoring
|
|
19
|
+
|
|
20
|
+
##❌ Incorrect
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
# ❌ No type hints
|
|
24
|
+
def get_user(id):
|
|
25
|
+
return users.get(id)
|
|
26
|
+
|
|
27
|
+
def process_order(order, discount):
|
|
28
|
+
if discount:
|
|
29
|
+
return order['total'] * (1 - discount)
|
|
30
|
+
return order['total']
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## ✅ Correct
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
# ✅ Full type hints
|
|
37
|
+
from typing import Optional, Dict, Any
|
|
38
|
+
|
|
39
|
+
def get_user(id: int) -> Optional[Dict[str, Any]]:
|
|
40
|
+
"""Fetch user by ID.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
id: User ID
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
User dict or None if not found
|
|
47
|
+
"""
|
|
48
|
+
return users.get(id)
|
|
49
|
+
|
|
50
|
+
def process_order(order: Dict[str, Any], discount: Optional[float] = None) -> float:
|
|
51
|
+
"""Calculate order total with optional discount.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
order: Order dictionary with 'total' key
|
|
55
|
+
discount: Discount rate (0.0-1.0), e.g. 0.1 for 10% off
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Final price after discount
|
|
59
|
+
"""
|
|
60
|
+
if discount:
|
|
61
|
+
return order['total'] * (1 - discount)
|
|
62
|
+
return order['total']
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## TypeScript
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// ✅ Explicit types
|
|
69
|
+
interface User {
|
|
70
|
+
id: number;
|
|
71
|
+
name: string;
|
|
72
|
+
email: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getUser(id: number): User | null {
|
|
76
|
+
return users.get(id) ?? null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function processOrder(
|
|
80
|
+
order: { total: number },
|
|
81
|
+
discount?: number
|
|
82
|
+
): number {
|
|
83
|
+
if (discount) {
|
|
84
|
+
return order.total * (1 - discount);
|
|
85
|
+
}
|
|
86
|
+
return order.total;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## References
|
|
91
|
+
|
|
92
|
+
- [Python Type Hints](https://docs.python.org/3/library/typing.html)
|
|
93
|
+
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
|