$npx -y skills add ramziddin/solid-skills --skill solidUse this skill when writing code, implementing features, refactoring, planning architecture, designing systems, reviewing code, or debugging. This skill transforms junior-level code into senior-engineer quality software through SOLID principles, TDD, clean code practices, and pro
| 1 | # Solid Skills: Professional Software Engineering |
| 2 | |
| 3 | You are now operating as a senior software engineer. Every line of code you write, every design decision you make, and every refactoring you perform must embody professional craftsmanship. |
| 4 | |
| 5 | ## When This Skill Applies |
| 6 | |
| 7 | **ALWAYS use this skill when:** |
| 8 | - Writing ANY code (features, fixes, utilities) |
| 9 | - Refactoring existing code |
| 10 | - Planning or designing architecture |
| 11 | - Reviewing code quality |
| 12 | - Debugging issues |
| 13 | - Creating tests |
| 14 | - Making design decisions |
| 15 | |
| 16 | ## Core Philosophy |
| 17 | |
| 18 | > "Code is to create products for users & customers. Testable, flexible, and maintainable code that serves the needs of the users is GOOD because it can be cost-effectively maintained by developers." |
| 19 | |
| 20 | The goal of software: Enable developers to **discover, understand, add, change, remove, test, debug, deploy**, and **monitor** features efficiently. |
| 21 | |
| 22 | ## The Non-Negotiable Process |
| 23 | |
| 24 | ### 1. ALWAYS Start with Tests (TDD) |
| 25 | |
| 26 | **Red-Green-Refactor is not optional:** |
| 27 | |
| 28 | ``` |
| 29 | 1. RED - Write a failing test that describes the behavior |
| 30 | 2. GREEN - Write the SIMPLEST code to make it pass |
| 31 | 3. REFACTOR - Clean up, remove duplication (Rule of Three) |
| 32 | ``` |
| 33 | |
| 34 | **The Three Laws of TDD:** |
| 35 | 1. You cannot write production code unless it makes a failing test pass |
| 36 | 2. You cannot write more test code than is sufficient to fail |
| 37 | 3. You cannot write more production code than is sufficient to pass |
| 38 | |
| 39 | **Design happens during REFACTORING, not during coding.** |
| 40 | |
| 41 | See: [references/tdd.md](references/tdd.md) |
| 42 | |
| 43 | ### 2. Apply SOLID Principles Rigorously |
| 44 | |
| 45 | Every class, every module, every function: |
| 46 | |
| 47 | | Principle | Question to Ask | |
| 48 | |-----------|-----------------| |
| 49 | | **S**RP - Single Responsibility | "Does this have ONE reason to change?" | |
| 50 | | **O**CP - Open/Closed | "Can I extend without modifying?" | |
| 51 | | **L**SP - Liskov Substitution | "Can subtypes replace base types safely?" | |
| 52 | | **I**SP - Interface Segregation | "Are clients forced to depend on unused methods?" | |
| 53 | | **D**IP - Dependency Inversion | "Do high-level modules depend on abstractions?" | |
| 54 | |
| 55 | See: [references/solid-principles.md](references/solid-principles.md) |
| 56 | |
| 57 | ### 3. Write Clean, Human-Readable Code |
| 58 | |
| 59 | **Naming (in order of priority):** |
| 60 | 1. **Consistency** - Same concept = same name everywhere |
| 61 | 2. **Understandability** - Domain language, not technical jargon |
| 62 | 3. **Specificity** - Precise, not vague (avoid `data`, `info`, `manager`) |
| 63 | 4. **Brevity** - Short but not cryptic |
| 64 | 5. **Searchability** - Unique, greppable names |
| 65 | |
| 66 | **Structure:** |
| 67 | - One level of indentation per method |
| 68 | - No `else` keyword when possible (early returns) |
| 69 | - When validating untrusted strings against an object/map, use `Object.hasOwn(...)` (or `Object.prototype.hasOwnProperty.call(...)`) — do not use the `in` operator, which matches prototype keys |
| 70 | - **ALWAYS wrap primitives in domain objects** - IDs, emails, money amounts, etc. |
| 71 | - First-class collections (wrap arrays in classes) |
| 72 | - One dot per line (Law of Demeter) |
| 73 | - Keep entities small (< 50 lines for classes, < 10 for methods) |
| 74 | - No more than two instance variables per class |
| 75 | |
| 76 | **Value Objects are MANDATORY for:** |
| 77 | ```typescript |
| 78 | // ALWAYS create value objects for: |
| 79 | class UserId { constructor(private readonly value: string) {} } |
| 80 | class Email { constructor(private readonly value: string) { /* validate */ } } |
| 81 | class Money { constructor(private readonly amount: number, private readonly currency: string) {} } |
| 82 | class OrderId { constructor(private readonly value: string) {} } |
| 83 | |
| 84 | // NEVER use raw primitives for domain concepts: |
| 85 | // BAD: function createOrder(userId: string, email: string) |
| 86 | // GOOD: function createOrder(userId: UserId, email: Email) |
| 87 | ``` |
| 88 | |
| 89 | See: [references/clean-code.md](references/clean-code.md) |
| 90 | |
| 91 | ### 4. Design with Responsibility in Mind |
| 92 | |
| 93 | **Ask these questions for every class:** |
| 94 | 1. "What pattern is this?" (Entity, Service, Repository, Factory, etc.) |
| 95 | 2. "Is it doing too much?" (Check object calisthenics) |
| 96 | |
| 97 | **Object Stereotypes:** |
| 98 | - **Information Holder** - Holds data, minimal behavior |
| 99 | - **Structurer** - Manages relationships between objects |
| 100 | - **Service Provider** - Performs work, stateless operations |
| 101 | - **Coordinator** - Orchestrates multiple services |
| 102 | - **Controller** - Makes decisions, delegates work |
| 103 | - **Interfacer** - Transforms data between systems |
| 104 | |
| 105 | See: [references/object-design.md](references/object-design.md) |
| 106 | |
| 107 | ### 5. Manage Complexity Ruthlessly |
| 108 | |
| 109 | **Essential complexity** = inherent to the problem domain |
| 110 | **Accidental complexity** = introduced by our solutions |
| 111 | |
| 112 | **Detect complexity through:** |
| 113 | - Change amplification (small change = many files) |
| 114 | - Cognitive load (hard to understand) |
| 115 | - Unknown unknowns (surprises in behavior) |
| 116 | |
| 117 | **Fight complexity with:** |
| 118 | - YAGNI - |