clean-code
Clean code principles for readable, maintainable software
What this skill does
# Clean Code Principles
Write code that humans can understand. Code is read far more often than it's written.
## Naming
### Variables
```typescript
// BAD
const d = 86400000; // what is this?
const yyyymmdd = formatDate(date);
const list = getUsers();
// GOOD
const MILLISECONDS_PER_DAY = 86400000;
const formattedDate = formatDate(date);
const users = getUsers();
```
### Functions
```typescript
// BAD - unclear what it does
function handle(data) { }
function process(item) { }
function doIt() { }
// GOOD - verb + noun, describes action
function validateUserInput(input) { }
function calculateTotalPrice(items) { }
function sendWelcomeEmail(user) { }
```
### Booleans
```typescript
// BAD
const open = true;
const write = false;
const fruit = true;
// GOOD - is/has/can/should prefix
const isOpen = true;
const canWrite = false;
const hasFruit = true;
```
## Functions
### Single Responsibility
```typescript
// BAD - does too much
function createUserAndSendEmailAndLogActivity(data) {
const user = db.insert(data);
mailer.send(user.email, 'Welcome!');
logger.log(`User ${user.id} created`);
return user;
}
// GOOD - one thing each
function createUser(data) {
return db.insert(data);
}
function sendWelcomeEmail(user) {
mailer.send(user.email, 'Welcome!');
}
function logUserCreation(user) {
logger.log(`User ${user.id} created`);
}
```
### Few Parameters
```typescript
// BAD - too many parameters
function createUser(name, email, age, country, role, department, manager) { }
// GOOD - use object
function createUser(options: CreateUserOptions) { }
interface CreateUserOptions {
name: string;
email: string;
age?: number;
country?: string;
role: Role;
department?: string;
manager?: string;
}
```
### Avoid Flag Arguments
```typescript
// BAD - boolean changes behavior
function createFile(name: string, temp: boolean) {
if (temp) {
fs.create(`/tmp/${name}`);
} else {
fs.create(name);
}
}
// GOOD - separate functions
function createFile(name: string) {
fs.create(name);
}
function createTempFile(name: string) {
fs.create(`/tmp/${name}`);
}
```
### Return Early
```typescript
// BAD - nested conditionals
function getPayAmount(employee) {
let result;
if (employee.isSeparated) {
result = 0;
} else {
if (employee.isRetired) {
result = employee.pension;
} else {
result = employee.salary;
}
}
return result;
}
// GOOD - early returns
function getPayAmount(employee) {
if (employee.isSeparated) return 0;
if (employee.isRetired) return employee.pension;
return employee.salary;
}
```
## Comments
### Don't Comment Bad Code - Rewrite It
```typescript
// BAD
// Check if employee is eligible for benefits
if ((employee.flags & 0x0F) && (employee.age > 65)) { }
// GOOD - code explains itself
const isEligibleForBenefits = employee.hasHealthPlan && employee.isRetired;
if (isEligibleForBenefits) { }
```
### Good Comments
```typescript
// Regex matches ISO 8601 date format
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
// TODO: Refactor when API v2 launches
// WARNING: This must run before database migration
// NOTE: Third-party API has 100ms minimum delay
```
## Error Handling
### Don't Return Null
```typescript
// BAD
function getUser(id: string): User | null {
return db.find(id) || null;
}
// GOOD - throw or return Result type
function getUser(id: string): User {
const user = db.find(id);
if (!user) throw new UserNotFoundError(id);
return user;
}
// OR use Result type
function getUser(id: string): Result<User, NotFoundError> { }
```
### Don't Pass Null
```typescript
// BAD
function calculateArea(width: number | null, height: number | null) {
if (width === null || height === null) {
throw new Error('Invalid dimensions');
}
return width * height;
}
// GOOD - require valid inputs
function calculateArea(width: number, height: number) {
return width * height;
}
```
## Formatting
### Consistent Style
- Pick a style guide (Prettier, StandardJS, Black)
- Automate with formatters
- Never debate style in code review
### Vertical Density
```typescript
// BAD - unrelated code together
const user = getUser(id);
const config = loadConfig();
const result = processData(user, config);
logger.log(result);
sendNotification(user);
// GOOD - group related code
const user = getUser(id);
sendNotification(user);
const config = loadConfig();
const result = processData(user, config);
logger.log(result);
```
## Code Smells to Avoid
| Smell | Problem | Solution |
|-------|---------|----------|
| Long Method | Hard to understand | Extract methods |
| Long Parameter List | Complex interface | Parameter object |
| Duplicate Code | Change in multiple places | Extract function |
| Dead Code | Confusion, maintenance | Delete it |
| Magic Numbers | Unclear meaning | Named constants |
| Deep Nesting | Hard to follow | Early returns, extract |
| Feature Envy | Wrong location | Move method |
| Data Clumps | Always together | Create class |
## The Boy Scout Rule
> Leave the code cleaner than you found it.
Every commit should improve code quality slightly. Small, incremental improvements compound over time.
## Checklist
Before committing, ask:
- [ ] Can I understand this code in 6 months?
- [ ] Would a new team member understand it?
- [ ] Are names descriptive and searchable?
- [ ] Does each function do one thing?
- [ ] Are there any magic numbers/strings?
- [ ] Is error handling appropriate?
- [ ] Did I remove all dead code?
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.