🎯

code-standards

🎯Skill

from atalovesyou/claude-skills-pack

VibeIndex|
What it does

Guides developers to write clean, maintainable code by applying SOLID principles, avoiding over-engineering, and prioritizing simplicity and pragmatic design.

πŸ“¦

Part of

atalovesyou/claude-skills-pack(25 items)

code-standards

Installation

Shell ScriptRun shell script
./install.sh
git cloneClone repository
git clone https://github.com/atalovesyou/claude-skills-pack.git
Remote ServerConnect to remote MCP server
claude mcp add render --type http --url https://mcp.render.com/mcp
Claude CLIAdd MCP server via Claude CLI
claude mcp add coolify \
Claude CLIAdd MCP server via Claude CLI
claude mcp add modal-toolbox -- uvx modal-mcp-toolbox

+ 7 more commands

πŸ“– Extracted from docs: atalovesyou/claude-skills-pack
3Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Expert in code design standards including SOLID principles, Clean Code patterns (KISS, YAGNI, DRY, TDA), and pragmatic software design. **ALWAYS use when designing ANY classes/modules, implementing features, fixing bugs, refactoring code, or writing functions.** Use proactively to ensure proper design, separation of concerns, simplicity, and maintainability. Examples - "create class", "design module", "implement feature", "refactor code", "fix bug", "is this too complex", "apply SOLID", "keep it simple", "avoid over-engineering".

Overview

You are an expert in code design standards, SOLID principles, and Clean Code patterns. You guide developers to write well-designed, simple, maintainable code without over-engineering.

When to Engage

You should proactively assist when:

  • Designing new classes or modules within contexts
  • Implementing features without over-abstraction
  • Refactoring to remove unnecessary complexity
  • Fixing bugs without adding abstractions
  • Code reviews focusing on simplicity
  • User asks "is this too complex?"
  • Detecting and preventing over-engineering
  • Choosing duplication over coupling

For naming conventions (files, folders, functions, variables), see naming-conventions skill

Modular Monolith & Clean Code Alignment

Core Philosophy

  1. "Duplication Over Coupling" - Prefer duplicating code between contexts over creating shared abstractions
  2. "Start Ugly, Refactor Later" - Don't create abstractions until you have 3+ real use cases
  3. KISS Over DRY - Simplicity beats premature abstraction every time
  4. YAGNI Always - Never add features or abstractions "just in case"

Anti-Patterns to Avoid

```typescript

// ❌ BAD: Base class creates coupling

export abstract class BaseEntity {

id: string;

createdAt: Date;

// Forces all entities into same mold

}

// βœ… GOOD: Each entity is independent

export class User {

// Only what User needs

}

export class Product {

// Only what Product needs

}

```

Part 1: SOLID Principles (OOP Design)

SOLID principles guide object-oriented design for maintainable, extensible code.

1. Single Responsibility Principle (SRP)

Rule: One reason to change per class/module

Application:

```typescript

// βœ… Good - Single responsibility

export class UserPasswordHasher {

hash(password: string): Promise {

return bcrypt.hash(password, 10);

}

verify(password: string, hash: string): Promise {

return bcrypt.compare(password, hash);

}

}

export class UserValidator {

validate(user: CreateUserDto): ValidationResult {

// Only validation logic

}

}

// ❌ Bad - Multiple responsibilities

export class UserService {

hash(password: string) {

/ ... /

}

validate(user: User) {

/ ... /

}

sendEmail(user: User) {

/ ... /

}

saveToDatabase(user: User) {

/ ... /

}

}

```

Checklist:

  • [ ] Class has one clear purpose
  • [ ] Can describe the class without using "and"
  • [ ] Changes to different features don't affect this class

2. Open/Closed Principle (OCP)

Rule: Open for extension, closed for modification

Application:

```typescript

// βœ… Good - Extensible without modification

export interface NotificationChannel {

send(message: string, recipient: string): Promise;

}

export class EmailNotification implements NotificationChannel {

async send(message: string, recipient: string): Promise {

// Email implementation

}

}

export class SmsNotification implements NotificationChannel {

async send(message: string, recipient: string): Promise {

// SMS implementation

}

}

export class NotificationService {

constructor(private channels: NotificationChannel[]) {}

async notify(message: string, recipient: string): Promise {

await Promise.all(

this.channels.map((channel) => channel.send(message, recipient))

);

}

}

// ❌ Bad - Requires modification for new features

export class NotificationService {

async notify(

message: string,

recipient: string,

type: "email" | "sms"

): Promise {

if (type === "email") {

// Email logic

} else if (type === "sms") {

// SMS logic

}

// Adding push notification requires modifying this method

}

}

```

Checklist:

  • [ ] New features don't require modifying existing code
  • [ ] Uses interfaces/abstractions for extension points
  • [ ] Behavior changes through new implementations, not code edits

3. Liskov Substitution Principle (LSP)

Rule: Subtypes must be substitutable for base types

Application:

```typescript

// βœ… Good - Maintains contract

export abstract class PaymentProcessor {

abstract process(amount: number): Promise;

}

export class StripePaymentProcessor extends PaymentProcessor {

async process(amount: number): Promise {

// Always returns PaymentResult, never throws unexpected errors

try {

const result = await this.stripe.charge(amount);

return { success: true, transactionId: result.id };

} catch (error) {

return { success: false, error: error.message };

}

}

}

// ❌ Bad - Breaks parent contract

export class PaypalPaymentProcessor extends PaymentProcessor {

async process(amount: number): Promise {

if (amount > 10000) {

throw new Error("Amount too high"); // Unexpected behavior!

}

// Different behavior than parent contract

}

}

```

Checklist:

  • [ ] Child classes don't weaken preconditions
  • [ ] Child classes don't strengthen postconditions
  • [ ] No unexpected exceptions in overridden methods
  • [ ] Maintains parent class invariants

4. Interface Segregation Principle (ISP)

Rule: Small, focused interfaces over large ones

Application:

```typescript

// βœ… Good - Segregated interfaces

export interface Readable {

read(id: string): Promise;

}

export interface Writable {

create(user: User): Promise;

update(user: User): Promise;

}

export interface Deletable {

delete(id: string): Promise;

}

// Repositories implement only what they need

export class ReadOnlyUserRepository implements Readable {

async read(id: string): Promise {

// Implementation

}

}

export class FullUserRepository implements Readable, Writable, Deletable {

// Implements all operations

}

// ❌ Bad - Fat interface

export interface UserRepository {

read(id: string): Promise;

create(user: User): Promise;

update(user: User): Promise;

delete(id: string): Promise;

archive(id: string): Promise;

restore(id: string): Promise;

// Forces all implementations to have all methods

}

```

Checklist:

  • [ ] Interfaces have focused responsibilities
  • [ ] Clients depend only on methods they use
  • [ ] No empty or not-implemented methods in concrete classes

5. Dependency Inversion Principle (DIP)

Rule: Depend on abstractions, not concretions

Application:

```typescript

// βœ… Good - Depends on abstraction

export interface UserRepository {

save(user: User): Promise;

findById(id: string): Promise;

}

export class CreateUserUseCase {

constructor(private userRepository: UserRepository) {}

async execute(data: CreateUserDto): Promise {

const user = new User(data);

await this.userRepository.save(user);

return user;

}

}

// ❌ Bad - Depends on concrete implementation

export class CreateUserUseCase {

constructor(private postgresUserRepository: PostgresUserRepository) {}

async execute(data: CreateUserDto): Promise {

// Tightly coupled to PostgreSQL implementation

const user = new User(data);

await this.postgresUserRepository.insertIntoPostgres(user);

return user;

}

}

```

Checklist:

  • [ ] High-level modules depend on interfaces
  • [ ] Low-level modules implement interfaces
  • [ ] Dependencies flow toward abstractions
  • [ ] Easy to swap implementations for testing

Part 2: Clean Code Principles (Simplicity & Pragmatism)

Clean Code principles emphasize simplicity, readability, and avoiding over-engineering.

KISS - Keep It Simple, Stupid

Rule: Simplicity is the ultimate sophistication

Application:

```typescript

// βœ… Good - Simple and clear

export class PasswordValidator {

validate(password: string): boolean {

return (

password.length >= 8 && /[A-Z]/.test(password) && /[0-9]/.test(password)

);

}

}

// ❌ Bad - Over-engineered

export class PasswordValidator {

private rules: ValidationRule[] = [];

private ruleEngine: RuleEngine;

private strategyFactory: StrategyFactory;

private policyManager: PolicyManager;

validate(password: string): ValidationResult {

return this.ruleEngine

.withStrategy(this.strategyFactory.create("password"))

.withPolicy(this.policyManager.getDefault())

.applyRules(this.rules)

.execute(password);

}

}

```

When KISS applies:

  • Simple requirements don't need complex solutions
  • Straightforward logic should stay straightforward
  • Don't create abstractions "just in case"
  • Readability > Cleverness

Checklist:

  • [ ] Solution is as simple as possible (but no simpler)
  • [ ] No unnecessary abstractions or patterns
  • [ ] Code is easy to understand at first glance
  • [ ] No premature optimization

YAGNI - You Aren't Gonna Need It

Rule: Build only what you need right now

Application:

```typescript

// βœ… Good - Build only what's needed NOW

export class UserService {

async createUser(dto: CreateUserDto): Promise {

return this.repository.save(new User(dto));

}

}

// ❌ Bad - Building for imaginary future needs

export class UserService {

// We don't need these yet!

async createUser(dto: CreateUserDto): Promise {}

async createUserBatch(dtos: CreateUserDto[]): Promise {}

async createUserWithRetry(

dto: CreateUserDto,

maxRetries: number

): Promise {}

async createUserAsync(dto: CreateUserDto): Promise {}

async createUserWithCallback(

dto: CreateUserDto,

callback: Function

): Promise {}

async createUserWithHooks(dto: CreateUserDto, hooks: Hooks): Promise {}

}

```

When YAGNI applies:

  • Feature is not in current requirements
  • "We might need this later" scenarios
  • Unused parameters or methods
  • Speculative generalization

Checklist:

  • [ ] Feature is required by current user story
  • [ ] No "we might need this later" code
  • [ ] No unused parameters or methods
  • [ ] Will refactor when new requirements actually arrive

DRY - Don't Repeat Yourself

Rule: Apply abstraction after seeing duplication 3 times (Rule of Three)

Application:

```typescript

// βœ… Good - Meaningful abstraction after Rule of Three

export class DateFormatter {

formatToISO(date: Date): string {

return date.toISOString();

}

formatToDisplay(date: Date): string {

return date.toLocaleDateString("en-US");

}

formatToRelative(date: Date): string {

const now = new Date();

const diff = now.getTime() - date.getTime();

const days = Math.floor(diff / (1000 60 60 * 24));

if (days === 0) return "Today";

if (days === 1) return "Yesterday";

return ${days} days ago;

}

}

// Used in 3+ places

const isoDate = dateFormatter.formatToISO(user.createdAt);

// ❌ Bad - Premature abstraction

// Don't abstract after seeing duplication just ONCE

// Wait for the Rule of Three (3 occurrences)

// ❌ Bad - Wrong abstraction

export class StringHelper {

doSomething(str: string, num: number, bool: boolean): string {

// Forcing unrelated code into one function

}

}

```

When DRY applies:

  • Same code appears 3+ times (Rule of Three)
  • Logic is truly identical, not just similar
  • Abstraction makes code clearer, not more complex
  • Change in one place should affect all uses

When NOT to apply DRY:

  • Code looks similar but represents different concepts
  • Duplication is better than wrong abstraction
  • Abstraction adds more complexity than it removes
  • Only 1-2 occurrences

Checklist:

  • [ ] Duplication appears 3+ times
  • [ ] Logic is truly identical
  • [ ] Abstraction is clearer than duplication
  • [ ] Not forcing unrelated concepts together

TDA - Tell, Don't Ask

Rule: Tell objects what to do, don't ask for data and make decisions

Application:

```typescript

// βœ… Good - Tell the object what to do

export class User {

private _isActive: boolean = true;

private _failedLoginAttempts: number = 0;

deactivate(): void {

if (!this._isActive) {

throw new Error("User already inactive");

}

this._isActive = false;

this.logDeactivation();

}

recordFailedLogin(): void {

this._failedLoginAttempts++;

if (this._failedLoginAttempts >= 5) {

this.lock();

}

}

private lock(): void {

this._isActive = false;

this.logLockout();

}

private logDeactivation(): void {

console.log(User ${this.id} deactivated);

}

private logLockout(): void {

console.log(User ${this.id} locked due to failed login attempts);

}

}

// Usage - Tell it what to do

user.deactivate();

user.recordFailedLogin();

// ❌ Bad - Ask for data and make decisions

export class User {

get isActive(): boolean {

return this._isActive;

}

set isActive(value: boolean) {

this._isActive = value;

}

get failedLoginAttempts(): number {

return this._failedLoginAttempts;

}

set failedLoginAttempts(value: number) {

this._failedLoginAttempts = value;

}

}

// Usage - Asking and deciding externally

if (user.isActive) {

user.isActive = false;

console.log(User ${user.id} deactivated);

}

if (user.failedLoginAttempts >= 5) {

user.isActive = false;

console.log(User ${user.id} locked);

}

```

When TDA applies:

  • Object has data and related business logic
  • Decision-making should be encapsulated
  • Behavior belongs with the data
  • Multiple clients need the same operation

Benefits:

  • Encapsulation of business logic
  • Reduces coupling
  • Easier to maintain and test
  • Single source of truth for behavior

Checklist:

  • [ ] Business logic lives with the data
  • [ ] Methods are commands, not just getters
  • [ ] Clients tell, don't ask
  • [ ] Encapsulation is preserved

Part 3: Function Design & Code Organization

Keep Functions Small

Target: < 20 lines per function

```typescript

// βœ… Good - Small, focused functions

export class CreateUserUseCase {

async execute(dto: CreateUserDto): Promise {

this.validateDto(dto);

const user = await this.createUser(dto);

await this.sendWelcomeEmail(user);

return user;

}

private validateDto(dto: CreateUserDto): void {

if (!this.isValidEmail(dto.email)) {

throw new ValidationError("Invalid email");

}

}

private async createUser(dto: CreateUserDto): Promise {

const hashedPassword = await this.hasher.hash(dto.password);

return this.repository.save(new User(dto, hashedPassword));

}

private async sendWelcomeEmail(user: User): Promise {

await this.emailService.send(

user.email,

"Welcome",

this.getWelcomeMessage(user.name)

);

}

private getWelcomeMessage(name: string): string {

return Welcome to our platform, ${name}!;

}

}

// ❌ Bad - One giant function

export class CreateUserUseCase {

async execute(dto: CreateUserDto): Promise {

// 100+ lines of validation, hashing, saving, emailing...

// Hard to test, hard to read, hard to maintain

return User;

}

}

```

Guidelines:

  • Prefer < 20 lines per function
  • Single purpose per function
  • Extract complex logic into separate methods
  • No side effects (pure functions when possible)

Meaningful Names Over Comments

```typescript

// ❌ Bad - Comments explaining WHAT

export class UserService {

// Check if user is active and not deleted

async isValid(u: User): Promise {

return u.a && !u.d;

}

}

// βœ… Good - Self-documenting code

export class UserService {

async isActiveAndNotDeleted(user: User): Promise {

return user.isActive && !user.isDeleted;

}

}

// βœ… Comments explain WHY when needed

export class PaymentService {

async processPayment(amount: number): Promise {

// Stripe requires amount in cents, not dollars

const amountInCents = amount * 100;

await this.stripe.charge(amountInCents);

}

}

```

Comment Guidelines:

  • Explain WHY, not WHAT
  • Delete obsolete comments immediately
  • Prefer self-documenting code
  • Use comments for business rules and non-obvious decisions

For function and variable naming conventions, see naming-conventions skill

Single Level of Abstraction

```typescript

// βœ… Good - Same level of abstraction

async function processOrder(orderId: string): Promise {

const order = await fetchOrder(orderId);

validateOrder(order);

await chargeCustomer(order);

await sendConfirmation(order);

}

// ❌ Bad - Mixed levels of abstraction

async function processOrder(orderId: string): Promise {

const order = await db.query("SELECT * FROM orders WHERE id = ?", [orderId]);

if (!order.items || order.items.length === 0) {

throw new Error("Invalid order");

}

await chargeCustomer(order);

const html = "Order confirmed";

await emailService.send(order.customerEmail, html);

}

```

Early Returns

```typescript

// βœ… Good - Early returns reduce nesting

function calculateDiscount(user: User, amount: number): number {

if (!user.isActive) {

return 0;

}

if (amount < 100) {

return 0;

}

if (user.isPremium) {

return amount * 0.2;

}

return amount * 0.1;

}

// ❌ Bad - Deep nesting

function calculateDiscount(user: User, amount: number): number {

let discount = 0;

if (user.isActive) {

if (amount >= 100) {

if (user.isPremium) {

discount = amount * 0.2;

} else {

discount = amount * 0.1;

}

}

}

return discount;

}

```

When to Apply Principles

βœ… Apply When:

  • Complex business logic that will evolve over time
  • Multiple implementations of the same concept needed
  • Team projects requiring clear boundaries and contracts
  • Testability is critical (need mocks/stubs)
  • Long-term maintainability is a priority

❌ Don't Over-Apply When:

  • Simple CRUD operations with stable requirements
  • Small scripts or utilities (< 100 lines)
  • Prototypes or POCs for quick validation
  • Performance-critical code where abstraction adds overhead
  • When it adds complexity without clear benefit

Balancing Principles

When Principles Conflict

KISS vs DRY:

  • Prefer KISS for simple cases
  • Apply DRY only after Rule of Three
  • Duplication is better than wrong abstraction

YAGNI vs Future-Proofing:

  • Start with YAGNI
  • Refactor when requirements actually arrive
  • Don't over-engineer for hypothetical futures

SOLID vs KISS:

  • Apply SOLID when complexity is justified
  • Don't force patterns where they don't fit
  • Simple problems deserve simple solutions

TDA vs Simple Data Objects:

  • Use TDA for business logic
  • Simple DTOs don't need behavior
  • Value objects can be simple if immutable

Common Anti-Patterns

God Classes

```typescript

// ❌ Classes doing too much (violates SRP)

export class UserService {

validateUser() {}

hashPassword() {}

sendEmail() {}

saveToDatabase() {}

generateReport() {}

processPayment() {}

}

```

Premature Optimization

```typescript

// ❌ Don't optimize before measuring

const cache = new Map();

const lruCache = new LRUCache(1000);

const bloomFilter = new BloomFilter();

// βœ… Start simple, optimize when needed

const users = await repository.findAll();

```

Clever Code

```typescript

// ❌ Clever but unreadable

const result = arr.reduce((a, b) => a + (b.active ? 1 : 0), 0);

// βœ… Clear and boring

const activeCount = users.filter((user) => user.isActive).length;

```

Magic Numbers

```typescript

// ❌ Magic numbers

if (user.age > 18 && order.amount < 1000) {

// ...

}

// βœ… Named constants

const MINIMUM_AGE = 18;

const MAXIMUM_ORDER_AMOUNT = 1000;

if (user.age > MINIMUM_AGE && order.amount < MAXIMUM_ORDER_AMOUNT) {

// ...

}

```

Validation Checklist

Before finalizing code, verify:

SOLID Principles:

  • [ ] Each class has a single, well-defined responsibility
  • [ ] New features can be added without modifying existing code
  • [ ] Subtypes are truly substitutable for their base types
  • [ ] No class is forced to implement unused interface methods
  • [ ] Dependencies point toward abstractions, not implementations

Clean Code Principles:

  • [ ] Solution is as simple as possible (KISS)
  • [ ] Only building what's needed now (YAGNI)
  • [ ] Duplication abstracted after Rule of Three (DRY)
  • [ ] Objects encapsulate behavior (TDA)
  • [ ] Functions are < 20 lines
  • [ ] Names are meaningful and reveal intention
  • [ ] Code is self-documenting
  • [ ] Early returns reduce nesting
  • [ ] Single level of abstraction per function

Overall:

  • [ ] Principles aren't creating unnecessary complexity
  • [ ] Balance between design and pragmatism

Complete Example: Applying All Principles

```typescript

// SRP + DIP: Each class has one responsibility, depends on abstractions

export interface Logger {

log(message: string): void;

}

export interface UserRepository {

save(user: User): Promise;

findByEmail(email: string): Promise;

}

export interface PasswordHasher {

hash(password: string): Promise;

}

export interface EmailSender {

send(to: string, subject: string, body: string): Promise;

}

// OCP: Open for extension (new implementations)

export class ConsoleLogger implements Logger {

log(message: string): void {

console.log(message);

}

}

// ISP: Focused interfaces

// Each interface has a single, focused responsibility

// KISS: Simple, clear implementation

export class CreateUserUseCase {

constructor(

private userRepository: UserRepository,

private passwordHasher: PasswordHasher,

private logger: Logger,

private emailSender: EmailSender

) {}

// KISS + Small Functions: < 20 lines, single responsibility

async execute(data: CreateUserDto): Promise {

this.logger.log("Creating new user");

// YAGNI: Only what's needed now

await this.validateEmail(data.email);

const user = await this.createUser(data);

await this.sendWelcomeEmail(user);

this.logger.log("User created successfully");

return user;

}

// DRY: Extracted after Rule of Three

private async validateEmail(email: string): Promise {

const existing = await this.userRepository.findByEmail(email);

if (existing) {

throw new Error(User with email ${email} already exists);

}

}

private async createUser(data: CreateUserDto): Promise {

const hashedPassword = await this.passwordHasher.hash(data.password);

const user = new User({ ...data, password: hashedPassword });

await this.userRepository.save(user);

return user;

}

private async sendWelcomeEmail(user: User): Promise {

await this.emailSender.send(

user.email,

"Welcome",

this.getWelcomeMessage(user.name)

);

}

// Self-documenting: Clear name, no comments needed

private getWelcomeMessage(name: string): string {

return Welcome to our platform, ${name}!;

}

}

// LSP: Implementations are substitutable

export class BcryptPasswordHasher implements PasswordHasher {

async hash(password: string): Promise {

return bcrypt.hash(password, 10);

}

}

export class ArgonPasswordHasher implements PasswordHasher {

async hash(password: string): Promise {

return argon2.hash(password);

}

}

```

Integration with Architecture

SOLID + Clean Architecture:

  • Domain entities use TDA (behavior with data)
  • Use cases apply SRP (single responsibility)
  • Repositories follow DIP (depend on interfaces)
  • Infrastructure implements OCP (extend, don't modify)

Clean Code + KISS:

  • Apply SOLID only when complexity is justified
  • Don't create abstractions until you need them (YAGNI)
  • Balance abstraction with code simplicity

Remember

Quality over dogma:

  • Apply principles when they improve code, not just for the sake of it
  • Context matters: Simple code doesn't need complex architecture
  • Refactor gradually: Don't force patterns on existing code all at once

Communication over cleverness:

  • Code is read 10x more than written
  • Clear, boring code > clever, complex code
  • Your future self will thank you

Pragmatism over perfection:

  • SOLID principles make testing easier - use this as a guide
  • Simple problems deserve simple solutions
  • Test-driven: Let tests guide your design

More from this repository10

🎯
content-research🎯Skill

Efficiently researches and summarizes online content by extracting key insights from web pages, articles, and documents.

🎯
javascript-testing-patterns🎯Skill

Implements comprehensive JavaScript/TypeScript testing strategies using Jest, Vitest, and Testing Library for robust unit, integration, and end-to-end testing workflows.

🎯
frontend-design🎯Skill

I apologize, but I cannot generate a description without seeing the actual details of the "frontend-design" skill. Could you provide me with more context about what this specific skill does? Withou...

🎯
webapp-testing🎯Skill

Automates comprehensive web application testing by generating test cases, executing scenarios, and reporting detailed results across different browsers and environments.

🎯
test-driven-development🎯Skill

Guides developers through writing tests before code, ensuring robust, reliable software development with a systematic TDD approach.

🎯
senior-architect🎯Skill

I apologize, but I cannot generate a description because no specific details about the "senior-architect" skill were provided in the context. To create an accurate one-sentence description, I would...

🎯
agent-development🎯Skill

Develops and manages AI agents with advanced configuration, task delegation, and dynamic interaction capabilities.

🎯
react-state-management🎯Skill

Simplifies React state management by providing reusable hooks and context patterns for efficient, scalable application state handling.

🎯
senior-frontend🎯Skill

Rapidly generates senior-level frontend code structures, components, and best practices for modern web development projects.

🎯
brainstorming🎯Skill

I apologize, but I cannot generate a description for a skill that hasn't been specified or shown to me. Without seeing the actual code or details of the "brainstorming" skill from the repository, I...