swe
Software Engineering
Core Principles
| Principle | Meaning |
|---|---|
| Simplicity | Simplest code that works; complexity only when required |
| Single Responsibility | Each function/class/module does one thing |
| Self-Documenting | Code explains itself; comments are a smell |
| Fail Fast | Validate early, propagate unexpected errors |
| Test Behavior | What code does, not implementation |
| No Backwards Compat | Don't add legacy support unless requested |
| Consistency | Match project conventions over preference |
Design
SOLID
| Principle | Violation Sign |
|---|---|
| Single Responsibility | Class doing too many things |
| Open/Closed | Modifying existing code for new features |
| Liskov Substitution | Overridden methods breaking contracts |
| Interface Segregation | Clients depend on unused methods |
| Dependency Inversion | High-level imports low-level details |
Architecture
Presentation → Application → Domain ← Infrastructure
↓
Dependencies point DOWN only
Rules:
- Domain depends on nothing
- Infrastructure implements domain interfaces
- No circular dependencies
Design Patterns
Use when solving real problems, not preemptively:
| Pattern | Use When |
|---|---|
| Factory | Complex object creation |
| Builder | Many optional parameters |
| Adapter | Incompatible interfaces |
| Facade | Simplifying subsystem |
| Strategy | Runtime algorithm selection |
| Observer | Many dependents need notification |
Security
- Validate all external input (allowlists > denylists)
- Encrypt sensitive data at rest and transit
- Never log secrets
- Parameterized queries (SQL injection)
- Escape output (XSS)
Implementation
Naming
| Type | Convention | Example |
|---|---|---|
| Variables | camelCase noun | userName, isValid |
| Functions | camelCase verb | getUser, validateInput |
| Booleans | is/has/can prefix |
isActive, hasPermission |
| Constants | UPPER_SNAKE | MAX_RETRIES |
| Classes | PascalCase noun | UserService |
Rules:
- Names reveal intent
- No single-letter params
- No abbreviations (
ur→userRepository)
Self-Documenting Code
// ❌ Comment hiding bad code
if (u.r === 1 && u.s !== 0) { ... }
// ✅ Self-documenting
if (user.isAdmin && user.isActive) { ... }
Acceptable comments: RFC links, bug tracker refs, non-obvious warnings
Functions
| Do | Don't |
|---|---|
| Small, focused | God functions (100+ lines) |
| 2-3 params max | 6+ parameters |
| Return early | Deep nesting |
| Pure when possible | Hidden side effects |
| Single abstraction level | Mixed levels |
Error Handling
// ❌ Silent catch
try {
await save(user);
} catch (e) {}
// ❌ Log only
try {
await save(user);
} catch (e) {
console.log(e);
}
// ✅ Let propagate or handle specific
try {
await save(user);
} catch (e) {
if (e instanceof DuplicateEmail) return { error: "Email taken" };
throw e;
}
Rules:
- Empty catch = always wrong
- Catch only what you can handle
- Re-throw with context or propagate
- Crash visibly > fail silently
File Organization
- Match existing conventions
- No barrel files (
index.tsre-exports) - Import from concrete modules
- Co-locate tests with source
src/users/
user-service.ts
user-service.test.ts
Code Smells
| Smell | Fix |
|---|---|
| God Class | Split by responsibility |
| Feature Envy | Move method to data owner |
| Long Param List | Parameter object |
| Primitive Obsession | Value objects |
| Dead Code | Delete it |
Linting
| Tool | Purpose |
|---|---|
| Formatter | Style (Prettier, dprint) |
| Linter | Quality (ESLint, Ruff) |
| Type Checker | Safety (tsc, mypy) |
Rules:
- Automate formatting
- Zero warnings in CI
- Never disable rules—fix the code
Testing
Test Pyramid
E2E (few) - Critical journeys, slow
Integration (some) - Component interactions
Unit (many) - Fast, isolated, business logic
What to Test
| Test | Skip |
|---|---|
| Business logic | Framework code |
| Edge cases | Trivial getters |
| Error paths | Third-party libs |
| Public API | Private internals |
Test Quality
- Independent and isolated
- Deterministic (no flakiness)
- Fast (< 100ms unit)
- Single reason to fail
- Test behavior, not implementation
BDD Structure
describe("UserService", () => {
describe("given valid data", () => {
describe("when creating user", () => {
it("then persists with ID", async () => {
// arrange, act, assert
});
});
});
});
Anti-Patterns
| Pattern | Fix |
|---|---|
| Ice Cream Cone | More unit, fewer E2E |
| Flaky Tests | Fix races, use mocks |
| Testing Implementation | Test behavior |
| No Assertions | Add meaningful checks |
Review
Before PR
- Type check passes
- Lint passes
- Tests pass
- No debug/console.log
- No commented code
- Up to date with main
Review Checklist
Correctness:
- Does it work? Edge cases? Error handling?
Design:
- Right abstraction? SOLID? Dependencies appropriate?
Readability:
- Clear names? Straightforward logic? No unnecessary comments?
Security:
- Input validated? No injection? Secrets handled?
Performance:
- No N+1? No await in loops? Caching considered?
Tests:
- Sufficient coverage? Edge cases? Behavior-focused?
For Reviewers
- Code, not author
- Questions > demands
- Explain the "why"
- Blocking vs nitpick
For Authors
- Small, focused PRs
- Context in description
- Respond to all comments
Maintenance
Refactoring
- Ensure test coverage first
- Small, incremental changes
- Run tests after each change
- Refactor OR add features, never both
| Technique | When |
|---|---|
| Extract Method | Long method, reusable logic |
| Extract Class | Multiple responsibilities |
| Move Method | Uses other class's data more |
| Introduce Param Object | Long parameter lists |
Technical Debt
| Type | Handling |
|---|---|
| Deliberate | Document, schedule payback |
| Accidental | Fix when discovered |
| Bit Rot | Regular maintenance |
| Outdated Deps | Regular updates |
Find: unused code, duplicates, circular deps, outdated deps
Performance
- Don't optimize prematurely
- Measure before optimizing
- Focus on hot paths
| Pitfall | Fix |
|---|---|
| N+1 queries | Batch, joins |
| Blocking I/O | Async |
| Memory leaks | Weak refs, cleanup |
Documentation
| Document | Skip |
|---|---|
| Public APIs | Obvious code |
| ADRs | Implementation details |
| Setup/deploy | Self-documenting code |
| Non-obvious behavior | Every function |
Anti-Patterns
| Pattern | Problem | Fix |
|---|---|---|
| Big Ball of Mud | No structure | Define boundaries |
| Spaghetti Code | Tangled | Modularize |
| Lava Flow | Dead code | Delete it |
| Copy-Paste | Duplication | Extract |
| Magic Numbers | No context | Named constants |
| Circular Deps | Coupling | Abstraction layer |
| Feature Flags | Hidden complexity | One code path |
| Backwards Compat | Legacy burden | Replace entirely |
AI-Generated Debt
Code written by LLMs (including by this agent) accumulates specific debt patterns. Detect and fix on sight.
| Pattern | Description |
|---|---|
| Restating comments | Comment says what the next line does in different words |
| Boilerplate sprawl | Verbose wrappers, re-exports, adapters that add no value |
| Premature abstraction | Generic solution for a single use case |
| Convention drift | Each file follows a slightly different style |
| Cargo-cult error handling | try/catch everywhere with no actual recovery strategy |
| Orphan interfaces | Interface defined but only one implementor, no extension |
| Placeholder logic | TODO/stub/mock left behind, never replaced |
| Over-typing | Complex generics when a concrete type is clearer |
| Hallucinated API usage | Calling methods/options that don't exist in the actual lib |
| Copy-paste signatures | Same function shape repeated across files with minor changes |
Code Health Dimensions
When reviewing or writing code, assess across two axes.
Mechanical (verifiable by tools)
| Dimension | What to check |
|---|---|
| Dead code | Unused imports, exports, variables, functions |
| Duplication | Near-identical blocks across files |
| Complexity | Deep nesting, long functions, high cyclomatic count |
| Dependency | Import cycles, orphaned files, coupling violations |
| Test health | Critical paths without tests, flaky tests |
| Security | Unsanitized input, hardcoded secrets, SQL injection |
Subjective (requires judgment)
| Dimension | What to check |
|---|---|
| Naming quality | Do names communicate intent without reading the implementation? |
| Logic clarity | Can you follow control flow without mental stack overflow? |
| Error consistency | Same error strategy across modules, or a mix of patterns? |
| Abstraction fitness | Does each abstraction earn its cost with real leverage? |
| Contract coherence | Do functions honor their stated interfaces? |
| Cross-module arch | Dependency direction correct? Hub modules justified? |
| Convention consistency | Same patterns in sibling files? Or style islands? |
Prioritizing Fixes
| Tier | Effort | Examples |
|---|---|---|
| T1 | Auto-fixable | Unused imports, debug logs, formatting |
| T2 | Quick manual | Unused vars, dead exports, simple rename |
| T3 | Needs judgment | Near-duplicates, questionable abstraction |
| T4 | Major refactor | God class split, mixed-concern untangle |
Fix T1/T2 immediately. T3/T4 require a plan.
Acknowledging vs Hiding Debt
When leaving an issue unfixed:
- Document the decision - why it stays, not just that it does
- Track the cost - wontfix debt is still debt, it just has a reason
- Revisit periodically - reasons expire; what was acceptable 6 months ago may not be now
- Never dismiss to improve metrics - if the code is worse, admit it
More from knoopx/pi
podman
Manages containers, builds images, configures pods and networks with Podman. Use when running containers, creating Containerfiles, grouping services in pods, or managing container resources.
122jujutsu
Manages version control with Jujutsu (jj), including rebasing, conflict resolution, and Git interop. Use when tracking changes, navigating history, squashing/splitting commits, or pushing to Git remotes.
117nix-flakes
Creates reproducible builds, manages flake inputs, defines devShells, and builds packages with flake.nix. Use when initializing Nix projects, locking dependencies, or running nix build/develop commands.
54scraping
Fetches web pages, parses HTML with CSS selectors, calls REST APIs, and scrapes dynamic content. Use when extracting data from websites, querying JSON APIs, or automating browser interactions.
48jscpd
Finds duplicate code blocks and analyzes duplication metrics across files. Use when identifying copy-pasted code, measuring technical debt, or preparing for refactoring.
45yt-dlp
Downloads videos from YouTube and other sites using yt-dlp. Use when downloading videos, extracting metadata, or batch downloading multiple files.
42