| name | coding-standards |
| description | 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 for maintainability. |
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:
return email.lower()
GOOD
def normalize_email(email: str) -> str:
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