Fowler/Martin Code Refactoring Best Practices Comprehensive code refactoring guide based on Martin Fowler's catalog and Clean Code principles, designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation. When to Apply Reference these guidelines when: - Refactoring existing code to improve maintainability - Decomposing long methods or large classes - Reducing coupling between components - Simplifying complex conditional logic - Reviewing code for code smells and anti-patterns Rule Categories by Priority | Prio…

+ formattedAmount\n\n return priceWithSymbol\n}\n\nfunction getDiscount(customer: Customer): number {\n const isPremium = customer.tier === 'premium'\n const discount = isPremium ? 0.2 : 0\n\n return discount\n}\n```\n\n**Correct (inlined trivial expressions):**\n\n```typescript\nfunction isValidOrder(order: Order): boolean {\n return order.items.length > 0 &&\n order.customerId !== null &&\n order.status !== 'cancelled'\n}\n\nfunction formatPrice(amount: number): string {\n return '

Fowler/Martin Code Refactoring Best Practices Comprehensive code refactoring guide based on Martin Fowler's catalog and Clean Code principles, designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation. When to Apply Reference these guidelines when: - Refactoring existing code to improve maintainability - Decomposing long methods or large classes - Reducing coupling between components - Simplifying complex conditional logic - Reviewing code for code smells and anti-patterns Rule Categories by Priority | Prio…

+ (Math.round(amount * 100) / 100).toFixed(2)\n}\n\nfunction getDiscount(customer: Customer): number {\n return customer.tier === 'premium' ? 0.2 : 0\n}\n```\n\n**When NOT to inline:**\n- Variable name adds significant clarity to a complex expression\n- Variable is used multiple times\n- Expression has side effects (should only execute once)\n- Debugging benefits from inspecting intermediate values\n\n**Keep the variable when it documents intent:**\n\n```typescript\n// Keep - the name adds meaning\nfunction shouldShowWarning(user: User, action: Action): boolean {\n const hasDestructiveIntent = action.type === 'delete' || action.type === 'purge'\n const lacksConfirmation = !action.confirmed\n const isHighValueTarget = user.accountValue > 10000\n\n return hasDestructiveIntent && lacksConfirmation && isHighValueTarget\n}\n```\n\nReference: [Inline Variable](https://refactoring.com/catalog/inlineVariable.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2216,"content_sha256":"17f60774d9465e8619dd17249e075918eddcf3e1f2e9d3cd0aee4dc9655a7d74"},{"filename":"references/micro-remove-dead-code.md","content":"---\ntitle: Remove Dead Code\nimpact: LOW\nimpactDescription: reduces cognitive load and maintenance burden\ntags: micro, dead-code, cleanup, unused\n---\n\n## Remove Dead Code\n\nCode that is never executed confuses readers and creates maintenance burden. Delete it; version control preserves history if needed.\n\n**Incorrect (dead code left in place):**\n\n```typescript\nclass UserService {\n // Old method kept \"just in case\"\n // async getUser_OLD(id: string): Promise\u003cUser> {\n // return this.db.query('SELECT * FROM users WHERE id = ?', [id])\n // }\n\n async getUser(id: string): Promise\u003cUser> {\n return this.userRepository.findById(id)\n }\n\n // Method that's never called anywhere\n async getUsersByDepartment(deptId: string): Promise\u003cUser[]> {\n return this.userRepository.findByDepartment(deptId)\n }\n\n // Feature flag that's always false in production\n async getUsers(): Promise\u003cUser[]> {\n if (process.env.USE_LEGACY_QUERY === 'true') { // Never true\n return this.legacyGetUsers()\n }\n return this.userRepository.findAll()\n }\n\n // Dead code from abandoned feature\n private legacyGetUsers(): Promise\u003cUser[]> {\n // Old implementation no longer used\n return this.db.query('SELECT * FROM users_legacy')\n }\n}\n```\n\n**Correct (dead code removed):**\n\n```typescript\nclass UserService {\n async getUser(id: string): Promise\u003cUser> {\n return this.userRepository.findById(id)\n }\n\n async getUsers(): Promise\u003cUser[]> {\n return this.userRepository.findAll()\n }\n}\n\n// If getUsersByDepartment is needed later, recreate it from git history\n// git log -p --all -S 'getUsersByDepartment' -- '*.ts'\n```\n\n**Signs of dead code:**\n- Methods with no callers (IDE can detect)\n- Commented-out code blocks\n- Feature flags that are always false\n- Catch blocks that can never execute\n- Conditions that are always true/false\n\n**When NOT to delete:**\n- API endpoints that external systems might call\n- Hooks/callbacks registered with external frameworks\n- Code that appears dead but is invoked via reflection\n\nReference: [Remove Dead Code](https://refactoring.com/catalog/removeDeadCode.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2101,"content_sha256":"7d485d2b48bab66e0223e2c24753f5df59db4c398cb2a18445b7b843a9fbea04"},{"filename":"references/micro-rename-for-clarity.md","content":"---\ntitle: Rename for Clarity\nimpact: LOW\nimpactDescription: makes code self-documenting and reduces need for comments\ntags: micro, rename, clarity, refactoring\n---\n\n## Rename for Clarity\n\nWhen a name doesn't clearly convey meaning, rename it. Good names eliminate the need for explanatory comments.\n\n**Incorrect (unclear or misleading names):**\n\n```typescript\n// Single letters and abbreviations\nfunction calc(a: number, b: number, t: string): number {\n if (t === 'add') return a + b\n if (t === 'sub') return a - b\n return 0\n}\n\n// Generic names\nfunction processData(data: unknown[]): void {\n for (const item of data) {\n doStuff(item)\n }\n}\n\n// Names that don't match behavior\nfunction validateUser(user: User): User { // Doesn't just validate\n user.lastValidated = new Date()\n user.status = 'active'\n return user\n}\n\n// Misleading boolean names\nconst isReady = loadingComplete && !hasError && itemCount > 0\n// Should processing continue if isReady is true or false?\n```\n\n**Correct (clear, intention-revealing names):**\n\n```typescript\n// Descriptive parameter names\nfunction calculate(\n firstOperand: number,\n secondOperand: number,\n operation: 'add' | 'subtract'\n): number {\n if (operation === 'add') return firstOperand + secondOperand\n if (operation === 'subtract') return firstOperand - secondOperand\n return 0\n}\n\n// Specific names for specific types\nfunction sendNotifications(users: User[]): void {\n for (const user of users) {\n notifyUser(user)\n }\n}\n\n// Name matches behavior\nfunction validateAndActivateUser(user: User): User {\n user.lastValidated = new Date()\n user.status = 'active'\n return user\n}\n\n// Boolean name answers \"should we X?\"\nconst shouldProcessItems = loadingComplete && !hasError && itemCount > 0\nif (shouldProcessItems) {\n processItems()\n}\n```\n\n**Rename method:**\n1. Use IDE's rename refactoring (updates all references)\n2. Run tests to verify nothing broke\n3. If the name appears in logs/databases, plan migration\n\nReference: [Rename Variable](https://refactoring.com/catalog/renameVariable.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2048,"content_sha256":"97c5f42b06d24bce3a32914f3d45548518cb0bf7bd18b6ef8df7a49365c134e7"},{"filename":"references/micro-simplify-expressions.md","content":"---\ntitle: Simplify Boolean Expressions\nimpact: LOW\nimpactDescription: improves readability and reduces cognitive load\ntags: micro, boolean, simplification, expressions\n---\n\n## Simplify Boolean Expressions\n\nComplex boolean expressions can often be simplified. Apply boolean algebra and use language features to make conditions clearer.\n\n**Incorrect (overly complex boolean logic):**\n\n```typescript\n// Double negatives\nif (!user.isNotActive) {\n activateFeatures()\n}\n\n// Redundant comparisons\nif (isValid === true) {\n process()\n}\nif (count !== 0) {\n showItems()\n}\n\n// Unnecessarily complex conditions\nif (status === 'active' || status === 'pending' || status === 'processing') {\n handleInProgress()\n}\n\n// Redundant else\nfunction isEligible(user: User): boolean {\n if (user.age >= 18) {\n return true\n } else {\n return false\n }\n}\n\n// Nested ternaries\nconst label = isAdmin ? 'Admin' : isManager ? 'Manager' : isEmployee ? 'Employee' : 'Guest'\n```\n\n**Correct (simplified expressions):**\n\n```typescript\n// Remove double negative\nif (user.isActive) {\n activateFeatures()\n}\n\n// Simplify comparisons\nif (isValid) {\n process()\n}\nif (count) { // Or: if (count > 0) for explicit intent\n showItems()\n}\n\n// Use includes for multiple equality checks\nconst inProgressStatuses = ['active', 'pending', 'processing']\nif (inProgressStatuses.includes(status)) {\n handleInProgress()\n}\n\n// Return the expression directly\nfunction isEligible(user: User): boolean {\n return user.age >= 18\n}\n\n// Use object lookup instead of nested ternaries\nconst roleLabels: Record\u003cstring, string> = {\n admin: 'Admin',\n manager: 'Manager',\n employee: 'Employee'\n}\nconst label = roleLabels[user.role] ?? 'Guest'\n```\n\n**Common simplifications:**\n- `if (x === true)` → `if (x)`\n- `if (x === false)` → `if (!x)`\n- `if (arr.length !== 0)` → `if (arr.length)`\n- `x ? true : false` → `Boolean(x)` or `!!x`\n- `!(!x)` → `x`\n\nReference: [Simplify Conditional Expression](https://refactoring.com/catalog/consolidateConditionalExpression.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2023,"content_sha256":"ed28345148a7ebcca117abef2c21222feaa484f5c0167f27230fc9151ae3763b"},{"filename":"references/name-avoid-abbreviations.md","content":"---\ntitle: Avoid Abbreviations and Acronyms\nimpact: HIGH\nimpactDescription: eliminates guesswork and reduces onboarding time\ntags: name, abbreviations, clarity, consistency\n---\n\n## Avoid Abbreviations and Acronyms\n\nAbbreviated names save keystrokes but cost comprehension time. Write out full words unless the abbreviation is universally understood.\n\n**Incorrect (cryptic abbreviations):**\n\n```typescript\ninterface UsrAcctDto {\n usrId: string\n acctNum: string\n curBal: number\n lstTxnDt: Date\n actv: boolean\n maxWdrwlAmt: number\n}\n\nfunction calcTotBal(accts: UsrAcctDto[]): number {\n return accts\n .filter(a => a.actv)\n .reduce((tot, a) => tot + a.curBal, 0)\n}\n\nconst mgr = getUserMgr()\nconst cfg = getAppCfg()\n```\n\n**Correct (spelled out for clarity):**\n\n```typescript\ninterface UserAccountDetails {\n userId: string\n accountNumber: string\n currentBalance: number\n lastTransactionDate: Date\n isActive: boolean\n maximumWithdrawalAmount: number\n}\n\nfunction calculateTotalBalance(accounts: UserAccountDetails[]): number {\n return accounts\n .filter(account => account.isActive)\n .reduce((total, account) => total + account.currentBalance, 0)\n}\n\nconst userManager = getUserManager()\nconst applicationConfig = getApplicationConfig()\n```\n\n**Acceptable abbreviations:**\n- Universally understood: `id`, `url`, `http`, `html`, `api`\n- Domain-specific standards: `isbn`, `sku`, `vin`\n- Loop counters: `i`, `j` in short loops\n- Well-established: `min`, `max`, `avg`, `prev`, `next`\n\n**When to keep abbreviations:**\n- External API uses them and consistency matters\n- Domain experts universally use the abbreviation\n- Full name would be excessively long (>30 characters)\n\nReference: [Clean Code - Meaningful Names](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1792,"content_sha256":"628408ac372ba6cf9712a8082d645c757da9fa36006dd94f5836ba3e3eec933f"},{"filename":"references/name-avoid-encodings.md","content":"---\ntitle: Avoid Type Encodings in Names\nimpact: HIGH\nimpactDescription: prevents name staleness and reduces visual clutter\ntags: name, encodings, hungarian-notation, prefixes\n---\n\n## Avoid Type Encodings in Names\n\nDon't embed type information in variable names. Modern IDEs show types on hover, and encoded types become lies when refactored.\n\n**Incorrect (type encodings in names):**\n\n```typescript\ninterface IUserService { // 'I' prefix for interface\n getUser(userId: string): User\n}\n\nclass UserServiceImpl implements IUserService { // 'Impl' suffix\n private strUserName: string // Hungarian notation\n private arrUserIds: string[] // Type in name\n private nUserCount: number // 'n' for number\n private bIsActive: boolean // 'b' for boolean\n private oUserConfig: UserConfig // 'o' for object\n private lstUsers: User[] // 'lst' for list\n\n getUserByIdString(userIdStr: string): User { // Redundant 'String'\n return this.userMapObject.get(userIdStr)\n }\n}\n```\n\n**Correct (clean names without encodings):**\n\n```typescript\ninterface UserService { // No 'I' prefix needed\n getUser(userId: string): User\n}\n\nclass DefaultUserService implements UserService { // Descriptive, not 'Impl'\n private userName: string\n private userIds: string[]\n private userCount: number\n private isActive: boolean\n private userConfig: UserConfig\n private users: User[]\n\n getUser(userId: string): User {\n return this.userMap.get(userId)\n }\n}\n```\n\n**Modern alternatives to prefixes:**\n- Instead of `IUserService`: Just `UserService` for interface, `HttpUserService` for implementation\n- Instead of `Impl` suffix: Use descriptive names like `CachedUserService`, `MockUserService`\n- Instead of Hungarian notation: Let the type system and IDE show types\n\n**When encodings are acceptable:**\n- Language conventions require them (C# interfaces commonly use `I`)\n- Distinguishing otherwise identical names (`abstract class User` vs `class UserEntity`)\n\nReference: [Clean Code - Meaningful Names](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2058,"content_sha256":"8662b717cfcb1cfb85b4cf504a0028efdfe0110ca36e7450bd48f121ec22c21a"},{"filename":"references/name-consistent-vocabulary.md","content":"---\ntitle: Use Consistent Vocabulary\nimpact: HIGH\nimpactDescription: eliminates confusion from synonyms and reduces mental mapping\ntags: name, consistency, vocabulary, ubiquitous-language\n---\n\n## Use Consistent Vocabulary\n\nPick one word for each concept and stick to it throughout the codebase. Mixing synonyms forces readers to wonder if different words mean different things.\n\n**Incorrect (inconsistent terms for same concept):**\n\n```typescript\nclass UserController {\n fetchUser(id: string): User { /* ... */ }\n}\n\nclass ProductController {\n getProduct(id: string): Product { /* ... */ }\n}\n\nclass OrderController {\n retrieveOrder(id: string): Order { /* ... */ }\n}\n\n// Elsewhere in the codebase\nconst customer = loadCustomer(id) // Is 'customer' different from 'user'?\nconst buyer = getBuyer(id) // Another synonym?\n\n// Data layer uses yet another term\nclass UserRepository {\n findById(id: string): User { /* ... */ }\n}\n```\n\n**Correct (consistent vocabulary throughout):**\n\n```typescript\n// Pick 'get' for all retrieval operations\nclass UserController {\n getUser(id: string): User { /* ... */ }\n}\n\nclass ProductController {\n getProduct(id: string): Product { /* ... */ }\n}\n\nclass OrderController {\n getOrder(id: string): Order { /* ... */ }\n}\n\n// Consistent term for the entity\nconst user = getUser(id) // Always 'user', never 'customer' or 'buyer'\n\n// Repository layer follows same convention\nclass UserRepository {\n getById(id: string): User { /* ... */ }\n}\n```\n\n**Establish conventions for:**\n- CRUD operations: `create/get/update/delete` or `add/fetch/modify/remove`\n- Collections: `list/find/search/filter` - pick one set\n- Status changes: `activate/deactivate` or `enable/disable`\n- Entity names: `user` vs `customer` vs `account`\n\nReference: [Domain-Driven Design - Ubiquitous Language](https://martinfowler.com/bliki/UbiquitousLanguage.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1862,"content_sha256":"6e8b142ad3034a56a5c36a04f850a7c26af5da87f58b338eff90be5de03606aa"},{"filename":"references/name-intention-revealing.md","content":"---\ntitle: Use Intention-Revealing Names\nimpact: HIGH\nimpactDescription: reduces code comprehension time by 40-60%\ntags: name, intention, readability, self-documenting\n---\n\n## Use Intention-Revealing Names\n\nNames should reveal why something exists, what it does, and how it is used. A reader should understand the purpose without reading the implementation.\n\n**Incorrect (cryptic or generic names):**\n\n```typescript\nfunction proc(lst: number[]): number {\n let t = 0\n for (const x of lst) {\n if (x > 0) {\n t += x\n }\n }\n return t\n}\n\nconst d = getD()\nconst flag = checkFlag(d)\nif (flag) {\n proc(d.n)\n}\n```\n\n**Correct (intention-revealing names):**\n\n```typescript\nfunction sumPositiveValues(values: number[]): number {\n let total = 0\n for (const value of values) {\n if (value > 0) {\n total += value\n }\n }\n return total\n}\n\nconst transaction = getTransaction()\nconst isApproved = isTransactionApproved(transaction)\nif (isApproved) {\n sumPositiveValues(transaction.amounts)\n}\n```\n\n**Naming guidelines:**\n- Variables: Describe what they hold (`customerEmail`, not `str` or `data`)\n- Functions: Describe what they do (`calculateShippingCost`, not `calc`)\n- Booleans: Use `is`, `has`, `can`, `should` prefixes (`isValid`, `hasPermission`)\n- Collections: Use plural nouns (`users`, `orderItems`)\n\nReference: [Clean Code - Meaningful Names](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1427,"content_sha256":"8607f5b85e7b8be9c578b2c2c537427d3555ca33fc12f31787779d39fe37532d"},{"filename":"references/name-searchable-names.md","content":"---\ntitle: Use Searchable Names\nimpact: HIGH\nimpactDescription: enables quick codebase navigation and reduces debugging time\ntags: name, searchable, constants, magic-numbers\n---\n\n## Use Searchable Names\n\nSingle-letter names and numeric constants are impossible to search for. Use named constants and descriptive variable names that can be grepped across the codebase.\n\n**Incorrect (unnamed constants and short names):**\n\n```typescript\nfunction calculatePrice(qty: number, p: number): number {\n if (qty > 10) {\n return p * qty * 0.9 // What is 0.9?\n }\n if (qty > 5) {\n return p * qty * 0.95 // What is 0.95?\n }\n return p * qty + 4.99 // What is 4.99?\n}\n\n// Trying to search for \"the 10% discount\" is impossible\n// Searching for \"0.9\" finds every unrelated decimal\n```\n\n**Correct (named constants and descriptive names):**\n\n```typescript\nconst BULK_ORDER_THRESHOLD = 10\nconst MEDIUM_ORDER_THRESHOLD = 5\nconst BULK_DISCOUNT_RATE = 0.10\nconst MEDIUM_DISCOUNT_RATE = 0.05\nconst STANDARD_SHIPPING_FEE = 4.99\n\nfunction calculatePrice(quantity: number, unitPrice: number): number {\n if (quantity > BULK_ORDER_THRESHOLD) {\n return unitPrice * quantity * (1 - BULK_DISCOUNT_RATE)\n }\n if (quantity > MEDIUM_ORDER_THRESHOLD) {\n return unitPrice * quantity * (1 - MEDIUM_DISCOUNT_RATE)\n }\n return unitPrice * quantity + STANDARD_SHIPPING_FEE\n}\n\n// Searching for \"BULK_DISCOUNT\" finds all related code instantly\n```\n\n**Name everything that has meaning:**\n- Thresholds and limits\n- Configuration values\n- Status codes and error codes\n- Array indices with special meaning\n- Regex patterns\n\nReference: [Clean Code - Meaningful Names](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":1708,"content_sha256":"dcf938341b96d085ed5f452572c8b4133d9b99691f03fc086bfc7b6384476ea4"},{"filename":"references/pattern-composition-over-inheritance.md","content":"---\ntitle: Prefer Composition Over Inheritance\nimpact: MEDIUM-HIGH\nimpactDescription: enables flexible behavior combination without class explosion\ntags: pattern, composition, inheritance, flexibility\n---\n\n## Prefer Composition Over Inheritance\n\nInheritance creates tight coupling and can lead to fragile base class problems. Compose objects by combining behaviors at runtime.\n\n**Incorrect (inheritance hierarchy for behavior combinations):**\n\n```typescript\nclass Animal {\n eat(): void { /* ... */ }\n}\n\nclass FlyingAnimal extends Animal {\n fly(): void { /* ... */ }\n}\n\nclass SwimmingAnimal extends Animal {\n swim(): void { /* ... */ }\n}\n\n// Problem: Duck can fly AND swim - which class to extend?\nclass FlyingSwimmingAnimal extends FlyingAnimal {\n swim(): void { /* ... */ } // Duplicated from SwimmingAnimal\n}\n\nclass Duck extends FlyingSwimmingAnimal {}\n\n// Adding walking, running, climbing leads to class explosion:\n// FlyingWalkingAnimal, SwimmingWalkingAnimal, FlyingSwimmingWalkingAnimal...\n```\n\n**Correct (composition of behaviors):**\n\n```typescript\ninterface Behavior {\n perform(): void\n}\n\nclass FlyingBehavior implements Behavior {\n perform(): void {\n console.log('Flying through the air')\n }\n}\n\nclass SwimmingBehavior implements Behavior {\n perform(): void {\n console.log('Swimming in water')\n }\n}\n\nclass WalkingBehavior implements Behavior {\n perform(): void {\n console.log('Walking on land')\n }\n}\n\nclass Animal {\n private behaviors: Behavior[] = []\n\n addBehavior(behavior: Behavior): void {\n this.behaviors.push(behavior)\n }\n\n performBehaviors(): void {\n this.behaviors.forEach(b => b.perform())\n }\n}\n\n// Duck composes the behaviors it needs\nconst duck = new Animal()\nduck.addBehavior(new FlyingBehavior())\nduck.addBehavior(new SwimmingBehavior())\nduck.addBehavior(new WalkingBehavior())\n\n// Penguin has different combination\nconst penguin = new Animal()\npenguin.addBehavior(new SwimmingBehavior())\npenguin.addBehavior(new WalkingBehavior())\n\n// Behaviors can even be changed at runtime\n```\n\n**When inheritance is appropriate:**\n- True \"is-a\" relationship with LSP compliance\n- Behavior rarely changes between subclasses\n- Framework requires it (React class components, etc.)\n\nReference: [Composition Over Inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2323,"content_sha256":"fc0dc6f163e10c443c4bfdabba17239d69ca791decbc1ceb241a743ac39c5112"},{"filename":"references/pattern-extract-superclass.md","content":"---\ntitle: Extract Superclass for Common Behavior\nimpact: MEDIUM-HIGH\nimpactDescription: eliminates duplication across related classes\ntags: pattern, extract-superclass, inheritance, duplication\n---\n\n## Extract Superclass for Common Behavior\n\nWhen two classes have similar features, extract common behavior into a superclass. This is appropriate when the classes represent variations of the same concept.\n\n**Incorrect (duplicated behavior across classes):**\n\n```typescript\nclass Employee {\n name: string\n annualSalary: number\n\n constructor(name: string, annualSalary: number) {\n this.name = name\n this.annualSalary = annualSalary\n }\n\n getMonthlyCost(): number {\n return this.annualSalary / 12\n }\n\n getName(): string {\n return this.name\n }\n\n getAnnualCost(): number {\n return this.annualSalary\n }\n}\n\nclass Contractor {\n name: string\n hourlyRate: number\n hoursPerMonth: number\n\n constructor(name: string, hourlyRate: number, hoursPerMonth: number) {\n this.name = name\n this.hourlyRate = hourlyRate\n this.hoursPerMonth = hoursPerMonth\n }\n\n getMonthlyCost(): number { // Same method name, different calculation\n return this.hourlyRate * this.hoursPerMonth\n }\n\n getName(): string { // Duplicated\n return this.name\n }\n\n getAnnualCost(): number { // Same method name, different calculation\n return this.getMonthlyCost() * 12\n }\n}\n```\n\n**Correct (extracted superclass):**\n\n```typescript\nabstract class Worker {\n constructor(protected name: string) {}\n\n getName(): string {\n return this.name\n }\n\n abstract getMonthlyCost(): number\n\n getAnnualCost(): number {\n return this.getMonthlyCost() * 12\n }\n}\n\nclass Employee extends Worker {\n constructor(name: string, private annualSalary: number) {\n super(name)\n }\n\n getMonthlyCost(): number {\n return this.annualSalary / 12\n }\n}\n\nclass Contractor extends Worker {\n constructor(\n name: string,\n private hourlyRate: number,\n private hoursPerMonth: number\n ) {\n super(name)\n }\n\n getMonthlyCost(): number {\n return this.hourlyRate * this.hoursPerMonth\n }\n}\n\n// Can now work with both types uniformly\nfunction calculateTotalMonthlyCost(workers: Worker[]): number {\n return workers.reduce((sum, worker) => sum + worker.getMonthlyCost(), 0)\n}\n```\n\n**When NOT to use:**\n- Classes don't represent the same conceptual category\n- Would violate Liskov Substitution Principle\n- Composition would be more flexible\n\nReference: [Extract Superclass](https://refactoring.com/catalog/extractSuperclass.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2523,"content_sha256":"02b4919d4ccf6c51bf8395207f9c90b038416567aa27aa1e43fd6322e6297f96"},{"filename":"references/pattern-factory.md","content":"---\ntitle: Use Factory for Complex Object Creation\nimpact: MEDIUM-HIGH\nimpactDescription: reduces duplication by 40-60% and enables isolated testing\ntags: pattern, factory, creation, encapsulation\n---\n\n## Use Factory for Complex Object Creation\n\nWhen object creation involves complex logic, validation, or conditional instantiation, encapsulate it in a factory. This separates creation concerns from business logic.\n\n**Incorrect (complex creation scattered throughout codebase):**\n\n```typescript\nclass OrderService {\n createOrder(data: OrderData): Order {\n // Complex creation logic repeated wherever orders are created\n const items = data.items.map(item => {\n const product = productRepository.find(item.productId)\n if (!product) throw new Error(`Product not found: ${item.productId}`)\n if (product.inventory \u003c item.quantity) {\n throw new Error(`Insufficient inventory for ${product.name}`)\n }\n return new OrderItem(product, item.quantity, product.price)\n })\n\n const customer = customerRepository.find(data.customerId)\n if (!customer) throw new Error('Customer not found')\n\n const shippingAddress = customer.addresses.find(a => a.id === data.addressId)\n if (!shippingAddress) throw new Error('Address not found')\n\n const order = new Order(customer, items, shippingAddress)\n order.calculateTotals()\n return order\n }\n}\n\n// Same creation logic duplicated in ImportService, MigrationService, etc.\n```\n\n**Correct (factory encapsulates creation):**\n\n```typescript\nclass OrderFactory {\n constructor(\n private productRepository: ProductRepository,\n private customerRepository: CustomerRepository\n ) {}\n\n create(data: OrderData): Order {\n const items = this.createOrderItems(data.items)\n const customer = this.getValidatedCustomer(data.customerId)\n const shippingAddress = this.getValidatedAddress(customer, data.addressId)\n\n const order = new Order(customer, items, shippingAddress)\n order.calculateTotals()\n return order\n }\n\n private createOrderItems(itemsData: OrderItemData[]): OrderItem[] {\n return itemsData.map(item => {\n const product = this.productRepository.find(item.productId)\n if (!product) throw new Error(`Product not found: ${item.productId}`)\n if (product.inventory \u003c item.quantity) {\n throw new Error(`Insufficient inventory for ${product.name}`)\n }\n return new OrderItem(product, item.quantity, product.price)\n })\n }\n\n private getValidatedCustomer(customerId: string): Customer {\n const customer = this.customerRepository.find(customerId)\n if (!customer) throw new Error('Customer not found')\n return customer\n }\n\n private getValidatedAddress(customer: Customer, addressId: string): Address {\n const address = customer.addresses.find(a => a.id === addressId)\n if (!address) throw new Error('Address not found')\n return address\n }\n}\n\n// Service is now simple\nclass OrderService {\n constructor(private orderFactory: OrderFactory) {}\n\n createOrder(data: OrderData): Order {\n return this.orderFactory.create(data)\n }\n}\n```\n\n**Benefits:**\n- Creation logic centralized and testable\n- Easy to create test doubles (TestOrderFactory)\n- Services focus on business logic, not object construction\n\nReference: [Factory Method Pattern](https://refactoring.guru/design-patterns/factory-method)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3350,"content_sha256":"5465272cc2f3098967c604eb316c85e3d6c71f9507feeac1ce7b64d70aa31e0a"},{"filename":"references/pattern-open-closed.md","content":"---\ntitle: Apply Open-Closed Principle\nimpact: MEDIUM-HIGH\nimpactDescription: enables extension without modifying existing tested code\ntags: pattern, ocp, solid, extensibility\n---\n\n## Apply Open-Closed Principle\n\nClasses should be open for extension but closed for modification. Design so that new behavior can be added without changing existing code.\n\n**Incorrect (requires modification for new types):**\n\n```typescript\nclass DiscountCalculator {\n calculate(order: Order): number {\n let discount = 0\n\n // Adding a new discount type requires modifying this method\n if (order.customer.isPremium) {\n discount += order.total * 0.1\n }\n\n if (order.items.length > 10) {\n discount += order.total * 0.05\n }\n\n if (order.coupon) {\n if (order.coupon.type === 'percentage') {\n discount += order.total * (order.coupon.value / 100)\n } else if (order.coupon.type === 'fixed') {\n discount += order.coupon.value\n }\n // New coupon type? Modify this method\n }\n\n if (isHolidaySeason()) {\n discount += order.total * 0.15\n }\n\n return Math.min(discount, order.total)\n }\n}\n```\n\n**Correct (extensible via new classes):**\n\n```typescript\ninterface DiscountRule {\n calculate(order: Order): number\n}\n\nclass PremiumCustomerDiscount implements DiscountRule {\n calculate(order: Order): number {\n return order.customer.isPremium ? order.total * 0.1 : 0\n }\n}\n\nclass BulkOrderDiscount implements DiscountRule {\n calculate(order: Order): number {\n return order.items.length > 10 ? order.total * 0.05 : 0\n }\n}\n\nclass CouponDiscount implements DiscountRule {\n calculate(order: Order): number {\n if (!order.coupon) return 0\n return order.coupon.type === 'percentage'\n ? order.total * (order.coupon.value / 100)\n : order.coupon.value\n }\n}\n\nclass DiscountCalculator {\n constructor(private rules: DiscountRule[]) {}\n\n calculate(order: Order): number {\n const totalDiscount = this.rules.reduce(\n (sum, rule) => sum + rule.calculate(order),\n 0\n )\n return Math.min(totalDiscount, order.total)\n }\n}\n\n// Adding new discount: create new class, inject it - no modification needed\nclass HolidayDiscount implements DiscountRule {\n calculate(order: Order): number {\n return isHolidaySeason() ? order.total * 0.15 : 0\n }\n}\n\nconst calculator = new DiscountCalculator([\n new PremiumCustomerDiscount(),\n new BulkOrderDiscount(),\n new CouponDiscount(),\n new HolidayDiscount() // Added without modifying DiscountCalculator\n])\n```\n\n**Benefits:**\n- New discount rules added without risk to existing rules\n- Each rule can be tested independently\n- Rules can be conditionally included at runtime\n\nReference: [Open-Closed Principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2776,"content_sha256":"f5425ace9a6887a35ee96376c5f3dabaedcfa7dea3202401d40afad8a150ecac"},{"filename":"references/pattern-strategy.md","content":"---\ntitle: Extract Strategy for Algorithm Variants\nimpact: MEDIUM-HIGH\nimpactDescription: enables runtime algorithm swapping and isolated testing\ntags: pattern, strategy, algorithm, composition\n---\n\n## Extract Strategy for Algorithm Variants\n\nWhen a class supports multiple algorithms for the same operation, extract each algorithm into its own strategy class. This allows runtime switching and independent testing.\n\n**Incorrect (algorithm variants embedded in class):**\n\n```typescript\nclass PaymentProcessor {\n processPayment(amount: number, method: string, details: PaymentDetails): PaymentResult {\n if (method === 'credit_card') {\n // 20 lines of credit card processing logic\n const encrypted = encryptCardData(details.cardNumber, details.cvv)\n const gateway = connectToStripeGateway()\n const auth = gateway.authorize(encrypted, amount)\n if (!auth.success) {\n return { success: false, error: auth.message }\n }\n const capture = gateway.capture(auth.transactionId)\n return { success: true, transactionId: capture.id }\n } else if (method === 'paypal') {\n // 15 lines of PayPal logic\n const redirect = initiatePayPalFlow(amount, details.returnUrl)\n // ...\n } else if (method === 'crypto') {\n // 25 lines of crypto payment logic\n const wallet = connectToWallet(details.walletAddress)\n // ...\n }\n throw new Error(`Unknown payment method: ${method}`)\n }\n}\n```\n\n**Correct (strategy pattern):**\n\n```typescript\ninterface PaymentStrategy {\n processPayment(amount: number, details: PaymentDetails): PaymentResult\n}\n\nclass CreditCardStrategy implements PaymentStrategy {\n processPayment(amount: number, details: PaymentDetails): PaymentResult {\n const encrypted = encryptCardData(details.cardNumber, details.cvv)\n const gateway = connectToStripeGateway()\n const auth = gateway.authorize(encrypted, amount)\n if (!auth.success) {\n return { success: false, error: auth.message }\n }\n const capture = gateway.capture(auth.transactionId)\n return { success: true, transactionId: capture.id }\n }\n}\n\nclass PayPalStrategy implements PaymentStrategy {\n processPayment(amount: number, details: PaymentDetails): PaymentResult {\n const redirect = initiatePayPalFlow(amount, details.returnUrl)\n // PayPal-specific logic\n return { success: true, transactionId: redirect.id }\n }\n}\n\nclass PaymentProcessor {\n constructor(private strategies: Map\u003cstring, PaymentStrategy>) {}\n\n processPayment(amount: number, method: string, details: PaymentDetails): PaymentResult {\n const strategy = this.strategies.get(method)\n if (!strategy) {\n throw new Error(`Unknown payment method: ${method}`)\n }\n return strategy.processPayment(amount, details)\n }\n}\n```\n\n**Benefits:**\n- Each strategy can be unit tested independently\n- New payment methods added without modifying PaymentProcessor\n- Strategies can be swapped at runtime (A/B testing)\n\nReference: [Strategy Pattern](https://refactoring.guru/design-patterns/strategy)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3032,"content_sha256":"eace33f2f303a98cc9a9aba53f9c3482adacc3fdd887a14808076a2797feb70d"},{"filename":"references/pattern-template-method.md","content":"---\ntitle: Use Template Method for Shared Skeleton\nimpact: MEDIUM-HIGH\nimpactDescription: eliminates duplicate control flow across similar algorithms\ntags: pattern, template-method, inheritance, skeleton\n---\n\n## Use Template Method for Shared Skeleton\n\nWhen multiple classes have similar algorithms with different steps, define the skeleton in a base class and let subclasses override specific steps.\n\n**Incorrect (duplicated algorithm structure):**\n\n```typescript\nclass PDFReportGenerator {\n generate(data: ReportData): void {\n this.logStart('PDF') // Duplicated\n const validated = this.validateData(data) // Duplicated\n if (!validated) throw new Error('Invalid data') // Duplicated\n\n // PDF-specific formatting\n const content = this.formatAsPDF(data)\n this.writeToPDF(content)\n\n this.logComplete('PDF') // Duplicated\n this.sendNotification() // Duplicated\n }\n}\n\nclass ExcelReportGenerator {\n generate(data: ReportData): void {\n this.logStart('Excel') // Duplicated\n const validated = this.validateData(data) // Duplicated\n if (!validated) throw new Error('Invalid data') // Duplicated\n\n // Excel-specific formatting\n const content = this.formatAsExcel(data)\n this.writeToExcel(content)\n\n this.logComplete('Excel') // Duplicated\n this.sendNotification() // Duplicated\n }\n}\n```\n\n**Correct (template method pattern):**\n\n```typescript\nabstract class ReportGenerator {\n // Template method defines the skeleton\n generate(data: ReportData): void {\n this.logStart()\n this.validateData(data)\n const content = this.formatContent(data) // Abstract - subclass implements\n this.writeOutput(content) // Abstract - subclass implements\n this.logComplete()\n this.sendNotification()\n }\n\n private logStart(): void {\n console.log(`Starting ${this.getReportType()} generation`)\n }\n\n private validateData(data: ReportData): void {\n if (!data.title || !data.rows.length) {\n throw new Error('Invalid report data')\n }\n }\n\n private logComplete(): void {\n console.log(`Completed ${this.getReportType()} generation`)\n }\n\n private sendNotification(): void {\n notifyReportComplete(this.getReportType())\n }\n\n // Hook methods for subclasses to implement\n protected abstract getReportType(): string\n protected abstract formatContent(data: ReportData): string\n protected abstract writeOutput(content: string): void\n}\n\nclass PDFReportGenerator extends ReportGenerator {\n protected getReportType(): string { return 'PDF' }\n\n protected formatContent(data: ReportData): string {\n return formatAsPDF(data)\n }\n\n protected writeOutput(content: string): void {\n writeToPDFFile(content)\n }\n}\n\nclass ExcelReportGenerator extends ReportGenerator {\n protected getReportType(): string { return 'Excel' }\n\n protected formatContent(data: ReportData): string {\n return formatAsExcel(data)\n }\n\n protected writeOutput(content: string): void {\n writeToExcelFile(content)\n }\n}\n```\n\n**Benefits:**\n- Algorithm skeleton defined once\n- Subclasses focus on what's different\n- Adding new report types only requires implementing abstract methods\n\nReference: [Template Method Pattern](https://refactoring.guru/design-patterns/template-method)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3222,"content_sha256":"41a91df9345c6abe2f77bc032307f8b38ac7caf392bd25c993276d84b62535e4"},{"filename":"references/struct-compose-method.md","content":"---\ntitle: Compose Method for Readable Flow\nimpact: CRITICAL\nimpactDescription: reduces cognitive load by 40-60%\ntags: struct, compose-method, readability, abstraction-levels\n---\n\n## Compose Method for Readable Flow\n\nTransform a method so that its body reads like a series of steps at the same level of abstraction. Each step should have a clear name that reveals its intent.\n\n**Incorrect (mixed abstraction levels):**\n\n```typescript\nasync function publishArticle(article: Article, author: User): Promise\u003cvoid> {\n // Low-level validation mixed with high-level flow\n if (!article.title || article.title.trim().length === 0) {\n throw new Error('Title required')\n }\n if (!article.content || article.content.length \u003c 100) {\n throw new Error('Content must be at least 100 characters')\n }\n if (!author.permissions.includes('publish')) {\n throw new Error('User cannot publish')\n }\n\n article.status = 'published'\n article.publishedAt = new Date()\n article.slug = article.title.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')\n\n await db.articles.update(article.id, article)\n\n const followers = await db.users.find({ following: author.id })\n for (const follower of followers) {\n await sendEmail(follower.email, `New article: ${article.title}`, article.excerpt)\n }\n\n await searchIndex.add({ id: article.id, title: article.title, content: article.content })\n}\n```\n\n**Correct (composed at consistent abstraction level):**\n\n```typescript\nasync function publishArticle(article: Article, author: User): Promise\u003cvoid> {\n validateArticleForPublishing(article)\n verifyPublishPermission(author)\n\n const publishedArticle = markAsPublished(article)\n await saveArticle(publishedArticle)\n\n await notifyFollowers(author, publishedArticle)\n await indexForSearch(publishedArticle)\n}\n\nfunction validateArticleForPublishing(article: Article): void {\n if (!article.title?.trim()) {\n throw new Error('Title required')\n }\n if (!article.content || article.content.length \u003c 100) {\n throw new Error('Content must be at least 100 characters')\n }\n}\n\nfunction verifyPublishPermission(author: User): void {\n if (!author.permissions.includes('publish')) {\n throw new Error('User cannot publish')\n }\n}\n\nfunction markAsPublished(article: Article): Article {\n return {\n ...article,\n status: 'published',\n publishedAt: new Date(),\n slug: generateSlug(article.title)\n }\n}\n\nfunction generateSlug(title: string): string {\n return title.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '')\n}\n```\n\n**Benefits:**\n- Main method reads like documentation\n- Each helper can be tested independently\n- Easy to modify individual steps without affecting others\n\nReference: [Compose Method Pattern](https://wiki.c2.com/?ComposeMethod)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2762,"content_sha256":"161a0cacae04d95016f6ffb04c35d9d1791865886c80285d187b1f792ae03cfb"},{"filename":"references/struct-extract-class.md","content":"---\ntitle: Extract Class from Large Class\nimpact: CRITICAL\nimpactDescription: improves testability and reduces cognitive load by 40-60%\ntags: struct, extract-class, decomposition, large-class\n---\n\n## Extract Class from Large Class\n\nWhen a class grows too large, it becomes difficult to understand and maintain. Extract cohesive groups of fields and methods into separate classes.\n\n**Incorrect (class doing too much):**\n\n```typescript\nclass Employee {\n name: string\n email: string\n phone: string\n street: string\n city: string\n state: string\n zipCode: string\n country: string\n\n getFullAddress(): string {\n return `${this.street}, ${this.city}, ${this.state} ${this.zipCode}, ${this.country}`\n }\n\n validateAddress(): boolean {\n return this.street.length > 0 && this.city.length > 0 && this.zipCode.length > 0\n }\n\n formatPhoneForDisplay(): string {\n return this.phone.replace(/(\\d{3})(\\d{3})(\\d{4})/, '($1) $2-$3')\n }\n\n getContactInfo(): string {\n return `${this.email} | ${this.formatPhoneForDisplay()}`\n }\n}\n```\n\n**Correct (extracted cohesive classes):**\n\n```typescript\nclass Employee {\n name: string\n contact: ContactInfo\n address: Address\n\n getContactInfo(): string {\n return this.contact.format()\n }\n\n getFullAddress(): string {\n return this.address.format()\n }\n}\n\nclass Address {\n constructor(\n public street: string,\n public city: string,\n public state: string,\n public zipCode: string,\n public country: string\n ) {}\n\n format(): string {\n return `${this.street}, ${this.city}, ${this.state} ${this.zipCode}, ${this.country}`\n }\n\n isValid(): boolean {\n return this.street.length > 0 && this.city.length > 0 && this.zipCode.length > 0\n }\n}\n\nclass ContactInfo {\n constructor(\n public email: string,\n public phone: string\n ) {}\n\n format(): string {\n return `${this.email} | ${this.formatPhone()}`\n }\n\n private formatPhone(): string {\n return this.phone.replace(/(\\d{3})(\\d{3})(\\d{4})/, '($1) $2-$3')\n }\n}\n```\n\n**Signs you need to extract:**\n- Groups of fields that are always used together\n- Methods that operate on a subset of fields\n- Fields with common prefixes (address_, contact_)\n\nReference: [Extract Class](https://refactoring.com/catalog/extractClass.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2250,"content_sha256":"9ac3163d97afe4b2a4f64479955379019473fc4dfb53dc92dba06f5aa9d4c4f1"},{"filename":"references/struct-extract-method.md","content":"---\ntitle: Extract Method for Long Functions\nimpact: CRITICAL\nimpactDescription: reduces function complexity by 50-80%\ntags: struct, extract-method, decomposition, readability\n---\n\n## Extract Method for Long Functions\n\nLong functions are the most common source of code complexity. Extract cohesive blocks of code into well-named methods to improve readability and enable reuse.\n\n**Incorrect (monolithic function with multiple responsibilities):**\n\n```typescript\nfunction processOrder(order: Order): ProcessedOrder {\n // Validate order\n if (!order.items || order.items.length === 0) {\n throw new Error('Order must have items')\n }\n if (!order.customer.email) {\n throw new Error('Customer email required')\n }\n\n // Calculate totals\n let subtotal = 0\n for (const item of order.items) {\n subtotal += item.price * item.quantity\n }\n const tax = subtotal * 0.1\n const shipping = subtotal > 100 ? 0 : 10\n const total = subtotal + tax + shipping\n\n // Format for display\n const formattedItems = order.items.map(item => ({\n name: item.name,\n display: `${item.name} x${item.quantity} - ${(item.price * item.quantity).toFixed(2)}`\n }))\n\n return { ...order, subtotal, tax, shipping, total, formattedItems }\n}\n```\n\n**Correct (decomposed into focused methods):**\n\n```typescript\nfunction processOrder(order: Order): ProcessedOrder {\n validateOrder(order)\n const totals = calculateTotals(order.items)\n const formattedItems = formatOrderItems(order.items)\n\n return { ...order, ...totals, formattedItems }\n}\n\nfunction validateOrder(order: Order): void {\n if (!order.items || order.items.length === 0) {\n throw new Error('Order must have items')\n }\n if (!order.customer.email) {\n throw new Error('Customer email required')\n }\n}\n\nfunction calculateTotals(items: OrderItem[]): OrderTotals {\n const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0)\n const tax = subtotal * 0.1\n const shipping = subtotal > 100 ? 0 : 10\n return { subtotal, tax, shipping, total: subtotal + tax + shipping }\n}\n\nfunction formatOrderItems(items: OrderItem[]): FormattedItem[] {\n return items.map(item => ({\n name: item.name,\n display: `${item.name} x${item.quantity} - ${(item.price * item.quantity).toFixed(2)}`\n }))\n}\n```\n\n**When to extract:**\n- Code block has a clear single purpose\n- Block is reusable in other contexts\n- Block requires its own documentation/testing\n\nReference: [Extract Function](https://refactoring.com/catalog/extractFunction.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2494,"content_sha256":"c046026da249256514f39e21c2e01fd3e20c3f4ab6c34c2f3bb690874896d8dc"},{"filename":"references/struct-function-length.md","content":"---\ntitle: Keep Functions Under 20 Lines\nimpact: CRITICAL\nimpactDescription: reduces cognitive load and bug density by 30-50%\ntags: struct, function-length, readability, complexity\n---\n\n## Keep Functions Under 20 Lines\n\nFunctions longer than 20 lines are harder to understand, test, and maintain. Research shows bug density increases with function length.\n\n**Incorrect (long function requiring scrolling):**\n\n```typescript\nfunction processPayment(order: Order, paymentMethod: PaymentMethod): PaymentResult {\n // Validate order\n if (!order.items.length) {\n return { success: false, error: 'Empty order' }\n }\n\n // Calculate amount\n let amount = 0\n for (const item of order.items) {\n amount += item.price * item.quantity\n }\n\n // Apply discounts\n if (order.couponCode) {\n const coupon = lookupCoupon(order.couponCode)\n if (coupon && coupon.expiresAt > new Date()) {\n if (coupon.type === 'percentage') {\n amount = amount * (1 - coupon.value / 100)\n } else {\n amount = amount - coupon.value\n }\n }\n }\n\n // Add tax\n const taxRate = getTaxRate(order.shippingAddress.state)\n amount = amount * (1 + taxRate)\n\n // Process payment\n let paymentResult\n if (paymentMethod.type === 'credit_card') {\n paymentResult = chargeCreditCard(paymentMethod.cardNumber, amount)\n } else if (paymentMethod.type === 'paypal') {\n paymentResult = chargePayPal(paymentMethod.email, amount)\n } else {\n return { success: false, error: 'Unknown payment method' }\n }\n\n // Handle result\n if (paymentResult.success) {\n updateOrderStatus(order.id, 'paid')\n sendConfirmationEmail(order.customer.email, order.id)\n return { success: true, transactionId: paymentResult.transactionId }\n } else {\n logPaymentFailure(order.id, paymentResult.error)\n return { success: false, error: paymentResult.error }\n }\n}\n```\n\n**Correct (composed of focused functions):**\n\n```typescript\nfunction processPayment(order: Order, paymentMethod: PaymentMethod): PaymentResult {\n const validationError = validateOrder(order)\n if (validationError) {\n return { success: false, error: validationError }\n }\n\n const amount = calculateFinalAmount(order)\n const paymentResult = executePayment(paymentMethod, amount)\n\n return handlePaymentResult(order, paymentResult)\n}\n\nfunction calculateFinalAmount(order: Order): number {\n const subtotal = calculateSubtotal(order.items)\n const discounted = applyDiscounts(subtotal, order.couponCode)\n return applyTax(discounted, order.shippingAddress.state)\n}\n\nfunction handlePaymentResult(order: Order, result: PaymentResult): PaymentResult {\n if (result.success) {\n updateOrderStatus(order.id, 'paid')\n sendConfirmationEmail(order.customer.email, order.id)\n } else {\n logPaymentFailure(order.id, result.error)\n }\n return result\n}\n```\n\n**When longer functions are acceptable:**\n- Complex algorithms that lose clarity when split\n- State machines with necessary sequential steps\n- Generated code or configuration\n\nReference: [Clean Code by Robert C. Martin](https://www.oreilly.com/library/view/clean-code-a/9780136083238/)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3099,"content_sha256":"e20385290b82c71291d0dcd36bb7c1c36a57e7645c16ee3eadb3e0d9f6b9f871"},{"filename":"references/struct-parameter-object.md","content":"---\ntitle: Introduce Parameter Object\nimpact: CRITICAL\nimpactDescription: reduces parameter count and enables behavior grouping\ntags: struct, parameter-object, data-clumps, api-design\n---\n\n## Introduce Parameter Object\n\nWhen multiple parameters frequently appear together, bundle them into a single object. This simplifies signatures and provides a home for related behavior.\n\n**Incorrect (long parameter list with data clumps):**\n\n```typescript\nfunction searchProducts(\n minPrice: number,\n maxPrice: number,\n category: string,\n inStock: boolean,\n sortBy: string,\n sortOrder: 'asc' | 'desc',\n page: number,\n pageSize: number\n): Product[] {\n // Implementation\n}\n\nfunction countProducts(\n minPrice: number,\n maxPrice: number,\n category: string,\n inStock: boolean\n): number {\n // Same filter params repeated\n}\n\n// Calling code is hard to read\nconst products = searchProducts(10, 100, 'electronics', true, 'price', 'asc', 1, 20)\n```\n\n**Correct (parameter object with behavior):**\n\n```typescript\ninterface ProductFilter {\n minPrice?: number\n maxPrice?: number\n category?: string\n inStock?: boolean\n}\n\ninterface PaginationOptions {\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n page?: number\n pageSize?: number\n}\n\nfunction searchProducts(filter: ProductFilter, pagination: PaginationOptions): Product[] {\n // Implementation\n}\n\nfunction countProducts(filter: ProductFilter): number {\n // Reuses same filter type\n}\n\n// Calling code is self-documenting\nconst filter: ProductFilter = { minPrice: 10, maxPrice: 100, category: 'electronics', inStock: true }\nconst pagination: PaginationOptions = { sortBy: 'price', sortOrder: 'asc', page: 1, pageSize: 20 }\nconst products = searchProducts(filter, pagination)\n```\n\n**Alternative (class with validation):**\n\n```typescript\nclass ProductFilter {\n constructor(\n public minPrice?: number,\n public maxPrice?: number,\n public category?: string,\n public inStock?: boolean\n ) {\n this.validate()\n }\n\n private validate(): void {\n if (this.minPrice !== undefined && this.maxPrice !== undefined && this.minPrice > this.maxPrice) {\n throw new Error('minPrice cannot exceed maxPrice')\n }\n }\n\n hasPrice(): boolean {\n return this.minPrice !== undefined || this.maxPrice !== undefined\n }\n}\n```\n\n**Benefits:**\n- Related parameters travel together\n- Validation logic has a natural home\n- Adding new parameters doesn't change function signatures\n\nReference: [Introduce Parameter Object](https://refactoring.com/catalog/introduceParameterObject.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2526,"content_sha256":"6a2ac01dc0281392b87c2fa15125739c75f0408baa5c983aeb738a81474c6040"},{"filename":"references/struct-replace-method-with-object.md","content":"---\ntitle: Replace Method with Method Object\nimpact: CRITICAL\nimpactDescription: enables extraction from complex methods with many local variables\ntags: struct, method-object, decomposition, local-variables\n---\n\n## Replace Method with Method Object\n\nWhen a long method has many local variables that make extraction difficult, turn the method into its own class. Local variables become instance fields, enabling easy decomposition.\n\n**Incorrect (method with many interdependent locals):**\n\n```typescript\nclass PriceCalculator {\n calculatePrice(order: Order): PriceBreakdown {\n let basePrice = 0\n let quantity = 0\n\n for (const item of order.items) {\n basePrice += item.unitPrice * item.quantity\n quantity += item.quantity\n }\n\n // Volume discount depends on quantity\n let volumeDiscount = 0\n if (quantity > 100) {\n volumeDiscount = basePrice * 0.15\n } else if (quantity > 50) {\n volumeDiscount = basePrice * 0.10\n } else if (quantity > 20) {\n volumeDiscount = basePrice * 0.05\n }\n\n // Loyalty discount depends on base price after volume\n const afterVolume = basePrice - volumeDiscount\n let loyaltyDiscount = 0\n if (order.customer.loyaltyYears > 5) {\n loyaltyDiscount = afterVolume * 0.10\n } else if (order.customer.loyaltyYears > 2) {\n loyaltyDiscount = afterVolume * 0.05\n }\n\n // Shipping depends on final price\n const subtotal = afterVolume - loyaltyDiscount\n let shipping = subtotal > 200 ? 0 : 15\n\n return { basePrice, volumeDiscount, loyaltyDiscount, shipping, total: subtotal + shipping }\n }\n}\n```\n\n**Correct (extracted to method object):**\n\n```typescript\nclass PriceCalculator {\n calculatePrice(order: Order): PriceBreakdown {\n return new PriceCalculation(order).compute()\n }\n}\n\nclass PriceCalculation {\n private basePrice = 0\n private quantity = 0\n private volumeDiscount = 0\n private loyaltyDiscount = 0\n private shipping = 0\n\n constructor(private order: Order) {}\n\n compute(): PriceBreakdown {\n this.calculateBasePrice()\n this.calculateVolumeDiscount()\n this.calculateLoyaltyDiscount()\n this.calculateShipping()\n\n return this.buildResult()\n }\n\n private calculateBasePrice(): void {\n for (const item of this.order.items) {\n this.basePrice += item.unitPrice * item.quantity\n this.quantity += item.quantity\n }\n }\n\n private calculateVolumeDiscount(): void {\n if (this.quantity > 100) {\n this.volumeDiscount = this.basePrice * 0.15\n } else if (this.quantity > 50) {\n this.volumeDiscount = this.basePrice * 0.10\n } else if (this.quantity > 20) {\n this.volumeDiscount = this.basePrice * 0.05\n }\n }\n\n private calculateLoyaltyDiscount(): void {\n const afterVolume = this.basePrice - this.volumeDiscount\n if (this.order.customer.loyaltyYears > 5) {\n this.loyaltyDiscount = afterVolume * 0.10\n } else if (this.order.customer.loyaltyYears > 2) {\n this.loyaltyDiscount = afterVolume * 0.05\n }\n }\n\n private calculateShipping(): void {\n const subtotal = this.basePrice - this.volumeDiscount - this.loyaltyDiscount\n this.shipping = subtotal > 200 ? 0 : 15\n }\n\n private buildResult(): PriceBreakdown {\n const subtotal = this.basePrice - this.volumeDiscount - this.loyaltyDiscount\n return {\n basePrice: this.basePrice,\n volumeDiscount: this.volumeDiscount,\n loyaltyDiscount: this.loyaltyDiscount,\n shipping: this.shipping,\n total: subtotal + this.shipping\n }\n }\n}\n```\n\n**Benefits:**\n- Each calculation step can be tested independently\n- Easy to add new discount types without modifying existing code\n- Local variables become visible state that can be inspected during debugging\n\nReference: [Replace Method with Method Object](https://refactoring.com/catalog/replaceFunctionWithCommand.html)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3820,"content_sha256":"b2b5d5d77ade073ee2b51e94050ea2194efa8a7904c641d4e984ec2e007edcd0"},{"filename":"references/struct-single-responsibility.md","content":"---\ntitle: Apply Single Responsibility Principle\nimpact: CRITICAL\nimpactDescription: reduces change impact radius by 60-90%\ntags: struct, srp, solid, class-design\n---\n\n## Apply Single Responsibility Principle\n\nA class should have only one reason to change. When a class handles multiple responsibilities, changes to one responsibility risk breaking others.\n\n**Incorrect (class with multiple responsibilities):**\n\n```typescript\nclass UserService {\n private users: Map\u003cstring, User> = new Map()\n\n createUser(data: UserData): User {\n const user = { id: crypto.randomUUID(), ...data }\n this.users.set(user.id, user)\n\n // Sending email is a separate responsibility\n const emailBody = `Welcome ${user.name}! Your account is ready.`\n this.sendEmail(user.email, 'Welcome', emailBody)\n\n // Logging is a separate responsibility\n console.log(`[${new Date().toISOString()}] User created: ${user.id}`)\n\n return user\n }\n\n private sendEmail(to: string, subject: string, body: string): void {\n // SMTP logic here\n }\n}\n```\n\n**Correct (separated responsibilities):**\n\n```typescript\nclass UserService {\n constructor(\n private userRepository: UserRepository,\n private notificationService: NotificationService,\n private logger: Logger\n ) {}\n\n createUser(data: UserData): User {\n const user = this.userRepository.create(data)\n this.notificationService.sendWelcomeEmail(user)\n this.logger.info('User created', { userId: user.id })\n return user\n }\n}\n\nclass UserRepository {\n private users: Map\u003cstring, User> = new Map()\n\n create(data: UserData): User {\n const user = { id: crypto.randomUUID(), ...data }\n this.users.set(user.id, user)\n return user\n }\n}\n\nclass NotificationService {\n sendWelcomeEmail(user: User): void {\n const body = `Welcome ${user.name}! Your account is ready.`\n this.sendEmail(user.email, 'Welcome', body)\n }\n\n private sendEmail(to: string, subject: string, body: string): void {\n // SMTP logic here\n }\n}\n```\n\n**Benefits:**\n- Each class can change independently\n- Classes are easier to test in isolation\n- Code is more reusable across different contexts\n\nReference: [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2241,"content_sha256":"7774c35f4239e7643225b57963c432fddd0db55dbed5c0b60b57614823625c95"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Fowler/Martin Code Refactoring Best Practices","type":"text"}]},{"type":"paragraph","content":[{"text":"Comprehensive code refactoring guide based on Martin Fowler's catalog and Clean Code principles, designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Apply","type":"text"}]},{"type":"paragraph","content":[{"text":"Reference these guidelines when:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Refactoring existing code to improve maintainability","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Decomposing long methods or large classes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reducing coupling between components","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Simplifying complex conditional logic","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Reviewing code for code smells and anti-patterns","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Rule Categories by Priority","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Priority","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Category","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Impact","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prefix","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"1","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Structure & Decomposition","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CRITICAL","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"struct-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"2","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Coupling & Dependencies","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CRITICAL","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"couple-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"3","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Naming & Clarity","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HIGH","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"name-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"4","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Conditional Logic","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HIGH","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cond-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"5","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Abstraction & Patterns","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MEDIUM-HIGH","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pattern-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"6","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Data Organization","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MEDIUM","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"data-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"7","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error Handling","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MEDIUM","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"error-","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"8","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Micro-Refactoring","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LOW","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"micro-","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Reference","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Structure & Decomposition (CRITICAL)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-extract-method","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Extract Method for Long Functions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-single-responsibility","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Apply Single Responsibility Principle","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-extract-class","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Extract Class from Large Class","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-compose-method","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Compose Method for Readable Flow","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-function-length","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Keep Functions Under 20 Lines","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-replace-method-with-object","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Method with Method Object","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"struct-parameter-object","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Introduce Parameter Object","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Coupling & Dependencies (CRITICAL)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-dependency-injection","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Dependency Injection","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-hide-delegate","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Hide Delegate to Reduce Coupling","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-remove-middle-man","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Remove Middle Man When Excessive","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-feature-envy","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Fix Feature Envy by Moving Methods","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-interface-segregation","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Apply Interface Segregation Principle","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"couple-preserve-whole-object","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Preserve Whole Object Instead of Fields","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Naming & Clarity (HIGH)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"name-intention-revealing","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Intention-Revealing Names","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"name-avoid-abbreviations","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Avoid Abbreviations and Acronyms","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"name-consistent-vocabulary","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Consistent Vocabulary","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"name-searchable-names","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Searchable Names","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"name-avoid-encodings","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Avoid Type Encodings in Names","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. Conditional Logic (HIGH)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-guard-clauses","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Nested Conditionals with Guard Clauses","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-polymorphism","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Conditional with Polymorphism","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-decompose","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Decompose Complex Conditionals","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-consolidate","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Consolidate Duplicate Conditional Fragments","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-special-case","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Introduce Special Case Object","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cond-lookup-table","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Conditional with Lookup Table","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. Abstraction & Patterns (MEDIUM-HIGH)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-strategy","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Extract Strategy for Algorithm Variants","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-template-method","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Template Method for Shared Skeleton","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-factory","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Factory for Complex Object Creation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-open-closed","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Apply Open-Closed Principle","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-composition-over-inheritance","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Prefer Composition Over Inheritance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"pattern-extract-superclass","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Extract Superclass for Common Behavior","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"6. Data Organization (MEDIUM)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"data-encapsulate-collection","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Encapsulate Collection","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"data-replace-primitive","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Primitive with Object","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"data-encapsulate-record","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Encapsulate Record into Class","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"data-split-variable","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Split Variable with Multiple Assignments","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"data-replace-temp-with-query","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Replace Temp with Query","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"7. Error Handling (MEDIUM)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"error-exceptions-over-codes","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Use Exceptions Instead of Error Codes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"error-custom-exceptions","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Create Domain-Specific Exception Types","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"error-fail-fast","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Fail Fast with Preconditions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"error-separate-concerns","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Separate Error Handling from Business Logic","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"8. Micro-Refactoring (LOW)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"micro-remove-dead-code","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Remove Dead Code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"micro-inline-variable","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Inline Trivial Variables","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"micro-simplify-expressions","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Simplify Boolean Expressions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"micro-rename-for-clarity","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Rename for Clarity","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"How to Use","type":"text"}]},{"type":"paragraph","content":[{"text":"Read individual reference files for detailed explanations and code examples:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Section definitions","type":"text","marks":[{"type":"link","attrs":{"href":"references/_sections.md","title":null}}]},{"text":" - Category structure and impact levels","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rule template","type":"text","marks":[{"type":"link","attrs":{"href":"assets/templates/_template.md","title":null}}]},{"text":" - Template for adding new rules","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Individual rules: ","type":"text"},{"text":"references/{prefix}-{slug}.md","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Full Compiled Document","type":"text"}]},{"type":"paragraph","content":[{"text":"For the complete guide with all rules expanded: ","type":"text"},{"text":"AGENTS.md","type":"text","marks":[{"type":"code_inline"}]}]}]},"metadata":{"date":"2026-11-02","name":"refactor","author":"@skillopedia","source":{"stars":220,"repo_name":"dot-skills","origin_url":"https://github.com/pproenca/dot-skills/blob/HEAD/skills/.curated/refactor/SKILL.md","repo_owner":"pproenca","body_sha256":"fec64e09a27e43d4435a314d51940ab0372f4a1c00b3d45d39cc8a9b5a7b2637","cluster_key":"20eaebeb0321c19d1cf9317a2891c9f2e11d7abd305aa54c689886a3a2fe3ac7","clean_bundle":{"format":"clean-skill-bundle-v1","source":"pproenca/dot-skills/skills/.curated/refactor/SKILL.md","text_bytes":121911,"source_commit":"cf93c57cac89d6fc3e4194686000411567f5caf3","skills_sh_rank":16858,"attachment_count":48,"text_attachments":48,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/.curated/refactor/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"software-engineering","category_label":"Engineering"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"software-engineering","import_tag":"skills-sh-top20k-2026-11","description":"Code refactoring best practices based on Martin Fowler's catalog and Clean Code principles (formerly refactoring). This skill should be used when refactoring existing code, improving code structure, reducing complexity, eliminating code smells, or reviewing code for maintainability. Triggers on tasks involving extract method, rename, decompose conditional, reduce coupling, or improve readability."}},"renderedAt":1793661321531}

Fowler/Martin Code Refactoring Best Practices Comprehensive code refactoring guide based on Martin Fowler's catalog and Clean Code principles, designed for AI agents and LLMs. Contains 43 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation. When to Apply Reference these guidelines when: - Refactoring existing code to improve maintainability - Decomposing long methods or large classes - Reducing coupling between components - Simplifying complex conditional logic - Reviewing code for code smells and anti-patterns Rule Categories by Priority | Prio…