DEV Community

Cover image for The HotfixHero code Manifesto: Seven Rules to Live By
HotfixHero
HotfixHero

Posted on

The HotfixHero code Manifesto: Seven Rules to Live By

I hear you. You want the technical specifications on how to stop being an embarrassment to your team. Fine. Writing code that scales and doesn’t induce chronic migraines is all about discipline, not magic. Forget your complex patterns for a second—master the basics first.

Here are the seven commandments I live by. Read them, implement them, and maybe, just maybe, your code review won't look like a war crime report.

The HotfixHero code Manifesto: Seven Rules to Live By

  • DRY (Don’t Repeat Yourself) Every piece of logic, every business rule, and every data definition must live in exactly one place. If you copy-paste, you're not coding; you're creating technical debt. The cost of fixing a bug multiplies by the number of times you repeated yourself. That's a terrible ROI.

Bad Example (Duplicate Validation):

function createUser(data) {
  if (data.password.length < 8 || data.email.includes(' ')) {
    throw new Error('Invalid input');
  }
  // User creation logic...
}

function updateUserPassword(data) {
  // Same exact validation repeated here
  if (data.newPassword.length < 8 || data.email.includes(' ')) {
    throw new Error('Invalid input');
  }
  // Password update logic...
}
Enter fullscreen mode Exit fullscreen mode

HH Way (Refactored to a Utility):

// Single source of truth for validation rules
function validateUserData(data) {
  if (data.password && data.password.length < 8) {
    throw new Error('Password too short');
  }
  if (data.email.includes(' ')) {
    throw new Error('Email must not contain spaces');
  }
}

function createUser(data) {
  validateUserData(data);
  // User creation logic...
}
Enter fullscreen mode Exit fullscreen mode
  • KISS (Keep It Simple, Stupid) The goal is to solve the problem, not win a Turing Award for the most convoluted solution. Simple code is cheaper to maintain, easier to test, and less likely to introduce subtle bugs. Your complexity doesn't impress anyone but junior developers.

Bad Example (Overly Complex Conditional):

function getDiscount(user) {
  let status = user.isPremium ? 0.20 : 
               (user.totalOrders > 5 && user.joinedYear < 2024) ? 0.15 : 
               user.totalOrders > 10 ? 0.10 : 0;

  // Now try debugging that nested ternary hell at 3 AM.
  return status;
}
Enter fullscreen mode Exit fullscreen mode

HH Way (Using Clear Logic):

function getDiscount(user) {
  if (user.isPremium) {
    return 0.20;
  }

  if (user.totalOrders > 5 && user.joinedYear < 2024) {
    return 0.15;
  }

  if (user.totalOrders > 10) {
    return 0.10;
  }

  return 0; // The default, simple case
}
Enter fullscreen mode Exit fullscreen mode
  • YAGNI (You Are Not Going to Need It) Stop guessing what the Product Owner might ask for next year. Build only what is required today. Every line of code you write that isn't solving a current problem is wasted time and creates unnecessary complexity.

Bad Example (Pre-building for Future Features):

# The current requirement is only 'File' storage.
# The developer adds hooks for 'S3' and 'Azure' just in case.
class StorageManager:
    def __init__(self, storage_type='FILE'): # <-- YAGNI violation
        if storage_type == 'FILE':
            self.driver = FileStorage()
        elif storage_type == 'S3':
            self.driver = S3Storage() # <-- Unused code path
        elif storage_type == 'AZURE':
            self.driver = AzureStorage() # <-- Unused code path
        else:
            raise ValueError("Invalid storage type")
Enter fullscreen mode Exit fullscreen mode

HH Way (Building Only What's Needed):

# If the only requirement is file storage, that's all we build.
class FileStorage:
    def save(self, data):
        # Implementation for saving to local disk
        pass

# When S3 is actually requested, we introduce the abstract concept and the new driver.
Enter fullscreen mode Exit fullscreen mode
  • SOLID (Single Responsibility Principle - SRP) Focus on SRP: A class or function should have only one reason to change. If your function is responsible for fetching data, formatting it, and sending an email, it's doing too much. When the email format changes, the fetching function shouldn't have to change.

Bad Example (God Function):

function processAndFormatUserData(id) {
  // 1. Fetch data (reason to change: database schema)
  const user = database.fetchUser(id); 

  // 2. Calculate Age (reason to change: calculation logic)
  const age = new Date().getFullYear() - new Date(user.dob).getFullYear();

  // 3. Format output (reason to change: UI/API requirement)
  return { id: user.id, fullName: `${user.first} ${user.last}`, age };
}
Enter fullscreen mode Exit fullscreen mode

HH Way (Separated Responsibilities):

// 1. Data Retrieval
function fetchUserFromDB(id): User {
  return database.fetchUser(id);
}

// 2. Business Logic/Calculation
function calculateAge(dob): number {
  return new Date().getFullYear() - new Date(dob).getFullYear();
}

// 3. Formatting/Presentation
function formatUserPresentation(user: User): UserDTO {
  return { 
    id: user.id, 
    fullName: `${user.first} ${user.last}`, 
    age: calculateAge(user.dob) // Calls focused logic
  };
}
Enter fullscreen mode Exit fullscreen mode
  • Separation of Concerns This principle is about dividing an application into distinct features that overlap as little as possible. Your data access layer shouldn't know about HTTP request headers, and your controller shouldn't contain complex formatting logic.

Bad Example (Mixing Data Access and Business Logic):

// Inside a Web Controller/Endpoint
@GetMapping("/users/{id}")
public UserDetails getUserDetails(@PathVariable Long id) {
    // Concern 1: Database Access is mixed here
    UserEntity user = entityManager.find(UserEntity.class, id); 

    // Concern 2: Business Logic is mixed here
    if (user.getBalance() < 0) {
        throw new IllegalStateException("User is in debt.");
    }

    // Concern 3: Formatting/Presentation Logic is mixed here
    UserDetails details = new UserDetails();
    details.setFullName(user.getFirstName() + " " + user.getLastName());
    return details;
}
Enter fullscreen mode Exit fullscreen mode

HH Way (Delegated Concerns):

  • Controller calls a Service layer.

  • Service layer contains business logic (e.g., checking balance).

  • Service layer calls a Repository layer for database access.

  • Avoid Premature Optimizations
    If you optimize before you measure, you are just making your code harder to read and more error-prone. Only optimize when you have proven, with a profiler, that a specific piece of code is the actual bottleneck.

Bad Example (Unnecessary Low-Level Loop for Readability Sacrifice):

// Bad: Using a simple 'for' loop and length decrement for micro-optimization
// Less readable than native methods, and modern engines optimize 'map' and 'forEach' just as well.
let i = items.length;
while (i--) {
  processed.push(items[i].toUpperCase());
}
Enter fullscreen mode Exit fullscreen mode

HH Way (Readable and Maintainable):

// Good: Clear intent, relies on optimized built-in methods.
const processed = items.map(item => item.toUpperCase());
Enter fullscreen mode Exit fullscreen mode
  • Law of Demeter (Principle of Least Knowledge) Don't talk to strangers. An object should only communicate with its immediate friends (objects it created, its parameters, its properties). Reaching through a chain of methods means your code is tightly coupled to deep internal structures, which is brittle.

Bad Example (Method Chaining Violation):

// We are asking the 'user' object for its 'wallet', then asking the 'wallet' for its 'card',
// then asking the 'card' for its 'security code'. Too much knowledge.
String code = user.getWallet().getPrimaryCard().getSecurityCode(); 
Enter fullscreen mode Exit fullscreen mode

HH Way (Delegation):

// We only ask the 'user' to perform the action. The user object handles the internal structure.
String code = user.getSecurityCodeForPrimaryCard(); 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)