clean-code

Clean code principles for readable, maintainable software

$ 설치

git clone https://github.com/majiayu000/claude-skill-registry /tmp/claude-skill-registry && cp -r /tmp/claude-skill-registry/skills/development/clean-code ~/.claude/skills/claude-skill-registry

// tip: Run this command in your terminal to install the skill


name: clean-code description: Clean code principles for readable, maintainable software

Clean Code Principles

Write code that humans can understand. Code is read far more often than it's written.

Naming

Variables

// 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

// 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

// 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

// 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

// 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

// 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

// 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

// 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

// 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

// 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

// 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

// 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

SmellProblemSolution
Long MethodHard to understandExtract methods
Long Parameter ListComplex interfaceParameter object
Duplicate CodeChange in multiple placesExtract function
Dead CodeConfusion, maintenanceDelete it
Magic NumbersUnclear meaningNamed constants
Deep NestingHard to followEarly returns, extract
Feature EnvyWrong locationMove method
Data ClumpsAlways togetherCreate 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?