All skills
asyrafhussin avatar

/clean-code-principles

@680deef

SOLID principles, design patterns, DRY, KISS, and clean code fundamentals. Use when reviewing architecture, checking code quality, refactoring, or discussing design decisions. Triggers on "review architecture", "check code quality", "SOLID principles", "design patterns", or "clean code".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/clean-code-principles

This session only. Nothing lands on disk.

rulessolid-ocp-extension.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Open/Closed Principle - Extension

Software entities should be open for extension but closed for modification. Add new functionality by adding new code, not by changing existing code.

Bad Example

// Anti-pattern: Modifying existing code to add new functionality
class PaymentProcessor {
  processPayment(payment: Payment): PaymentResult {
    switch (payment.method) {
      case 'credit_card':
        return this.processCreditCard(payment);
      case 'paypal':
        return this.processPayPal(payment);
      case 'stripe':
        return this.processStripe(payment);
      // Every new payment method requires modifying this class
      case 'apple_pay':
        return this.processApplePay(payment);
      case 'google_pay':
        return this.processGooglePay(payment);
      case 'crypto':
        return this.processCrypto(payment);
      default:
        throw new Error(`Unknown payment method: ${payment.method}`);
    }
  }

  private processCreditCard(payment: Payment): PaymentResult {
    // Credit card logic
  }

  private processPayPal(payment: Payment): PaymentResult {
    // PayPal logic
  }

  private processStripe(payment: Payment): PaymentResult {
    // Stripe logic
  }

  private processApplePay(payment: Payment): PaymentResult {
    // Apple Pay logic
  }

  private processGooglePay(payment: Payment): PaymentResult {
    // Google Pay logic
  }

  private processCrypto(payment: Payment): PaymentResult {
    // Crypto logic
  }
}

// Adding a new payment method requires:
// 1. Adding a new case to the switch statement
// 2. Adding a new private method
// 3. Testing the entire class again

Good Example

// Correct approach: Open for extension, closed for modification

// Define the contract for payment handlers
interface PaymentHandler {
  readonly methodType: string;
  canHandle(payment: Payment): boolean;
  process(payment: Payment): Promise<PaymentResult>;
  validate(payment: Payment): ValidationResult;
}

// Payment processor that never needs modification
class PaymentProcessor {
  private handlers: Map<string, PaymentHandler> = new Map();

  registerHandler(handler: PaymentHandler): void {
    this.handlers.set(handler.methodType, handler);
  }

  async processPayment(payment: Payment): Promise<PaymentResult> {
    const handler = this.handlers.get(payment.method);

    if (!handler) {
      throw new UnsupportedPaymentMethodError(payment.method);
    }

    const validation = handler.validate(payment);
    if (!validation.isValid) {
      throw new PaymentValidationError(validation.errors);
    }

    return handler.process(payment);
  }

  getSupportedMethods(): string[] {
    return Array.from(this.handlers.keys());
  }
}

// Each payment method is a separate class that can be added without modifying PaymentProcessor

class CreditCardPaymentHandler implements PaymentHandler {
  readonly methodType = 'credit_card';

  canHandle(payment: Payment): boolean {
    return payment.method === this.methodType;
  }

  validate(payment: Payment): ValidationResult {
    const errors: string[] = [];
    if (!payment.cardNumber || payment.cardNumber.length !== 16) {
      errors.push('Invalid card number');
    }
    if (!payment.cvv || payment.cvv.length !== 3) {
      errors.push('Invalid CVV');
    }
    return { isValid: errors.length === 0, errors };
  }

  async process(payment: Payment): Promise<PaymentResult> {
    // Credit card processing logic
    return { success: true, transactionId: generateId() };
  }
}

class PayPalPaymentHandler implements PaymentHandler {
  readonly methodType = 'paypal';

  canHandle(payment: Payment): boolean {
    return payment.method === this.methodType;
  }

  validate(payment: Payment): ValidationResult {
    const errors: string[] = [];
    if (!payment.paypalEmail) {
      errors.push('PayPal email required');
    }
    return { isValid: errors.length === 0, errors };
  }

  async process(payment: Payment): Promise<PaymentResult> {
    // PayPal processing logic
    return { success: true, transactionId: generateId() };
  }
}

// Adding a new payment method - no modification to existing code!
class CryptoPaymentHandler implements PaymentHandler {
  readonly methodType = 'crypto';

  canHandle(payment: Payment): boolean {
    return payment.method === this.methodType;
  }

  validate(payment: Payment): ValidationResult {
    const errors: string[] = [];
    if (!payment.walletAddress) {
      errors.push('Wallet address required');
    }
    if (!payment.cryptoCurrency) {
      errors.push('Cryptocurrency type required');
    }
    return { isValid: errors.length === 0, errors };
  }

  async process(payment: Payment): Promise<PaymentResult> {
    // Crypto processing logic
    return { success: true, transactionId: generateId() };
  }
}

// Application setup - register handlers
const processor = new PaymentProcessor();
processor.registerHandler(new CreditCardPaymentHandler());
processor.registerHandler(new PayPalPaymentHandler());
processor.registerHandler(new CryptoPaymentHandler());
// Add new payment methods by simply registering new handlers

Why

  1. Stability: The PaymentProcessor class is stable and tested. Adding new payment methods doesn't risk breaking existing functionality.

  2. Team Scalability: Different developers can work on different payment handlers simultaneously without merge conflicts.

  3. Plugin Architecture: Payment handlers can be loaded dynamically, even from external packages or plugins.

  4. Testing Isolation: Each handler is tested independently. New handlers don't require retesting old ones.

  5. Feature Flags: New payment methods can be enabled/disabled by simply registering or not registering the handler.

  6. Compliance: When regulations change for one payment method, only that handler needs updating.

  7. Rollback Safety: If a new payment handler has issues, remove it without touching proven code.

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill contains language-agnostic guidelines, examples, and reference material for clean code and SOLID principles. It consists purely of static documentation and contains no executable code or security risks.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    5/29 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 680deef. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
metadata
{
  "author": "AsyrafHussin",
  "version": "1.0.2"
}

README badge

README badge for asyrafhussin/agent-skills/clean-code-principles