coding-standards

Cross-language coding standards for Python, TypeScript, and Go covering naming, SOLID design, code smell removal, and comment philosophy. Use when writing, reviewing, or refactoring production code fo

SKILL.md

GitHub

Coding Standards

Write code that is obvious to change: clear names, small units, stable abstractions, and comments that explain intent rather than syntax.

When to Activate

  • Rename ambiguous identifiers
  • Split oversized functions or modules
  • Introduce a new abstraction or interface
  • Review a pull request for maintainability drift
  • Add comments around non-obvious behavior
  • Remove dead code after a feature change
  • Port logic between Python, TypeScript, and Go

Naming

Language Types Functions Variables Constants
Python PascalCase snake_case snake_case UPPER_SNAKE_CASE
TypeScript PascalCase camelCase camelCase UPPER_SNAKE_CASE for module constants
Go PascalCase exported, camelCase internal camelCase camelCase PascalCase or camelCase scoped to package

Rules:

  • Prefer names that reveal domain meaning, not implementation detail.
  • Boolean names should read as predicates: is_active, hasAccess, canRetry.
  • File names should match the dominant abstraction.

SOLID Without Ceremony

Principle Apply As Avoid
Single Responsibility One unit changes for one reason Utility files collecting unrelated behavior
Open/Closed Extend via composition, interfaces, data-driven config Switch chains duplicated across modules
Liskov Keep subtype behavior substitutable Hidden preconditions in implementations
Interface Segregation Small focused interfaces God interfaces with optional methods
Dependency Inversion Depend on abstractions at boundaries Concrete infrastructure leaking into business logic

Python

class PriceCalculator:
    def total(self, items: list[LineItem]) -> Decimal:
        return sum((item.total for item in items), start=Decimal("0"))

TypeScript

export interface PaymentGateway {
  charge(input: ChargeInput): Promise<ChargeResult>;
}

Code Smells

Smell Signal Refactor
Long function More than one phase or branching matrix Extract helpers by intent
Primitive obsession Raw strings for domain identifiers Introduce value objects or typed aliases
Shotgun surgery One rule changed in many files Centralize policy
Boolean parameter explosion doThing(x, true, false, true) Split commands or use typed options
Dead code Unreachable branches, unused exports Delete it

Comment Philosophy

Write Comments For Do Not Comment
Non-obvious constraints Syntax the reader can already see
External protocol quirks Temporary debugging leftovers
Performance tradeoffs Repeating function names in prose
Security-sensitive assumptions Commented-out dead code

BAD

def normalize_email(email: str) -> str:
    # Lowercase the email
    return email.lower()

GOOD

def normalize_email(email: str) -> str:
    # Login matching is case-insensitive across legacy providers.
    return email.strip().lower()

BAD

function handle(user: any, flag1: boolean, flag2: boolean) {
  if (flag1) {
    // ...
  }
}

GOOD

type HandleMode = "create" | "update";

interface HandleOptions {
  mode: HandleMode;
  sendNotification: boolean;
}

function handleUser(user: UserInput, options: HandleOptions) {
  if (options.mode === "create") {
    // ...
  }
}

No Speculative Abstractions

Situation Preferred Avoid
Unused helper after refactor Delete it in the same change Leave for "future use"
One implementation today Concrete type with clean seam Factory + interface + registry on day one
Feature flag fully rolled out Remove flag path Carry stale branches indefinitely

Checklist

  • Names encode domain meaning and read naturally
  • Each function has one clear job
  • Abstractions solve a present need, not a hypothetical one
  • Comments explain why a constraint exists
  • Unused code and commented-out blocks are removed
  • Boolean argument lists are replaced with clearer APIs where needed
  • Cross-module dependencies flow inward toward business logic
  • Examples and tests still compile after refactors