Guía de Principios de Ingeniería de Software y Código Limpio

1. KISS (Keep It Simple, Stupid)

Principio

KISS es un principio que sugiere que debemos mantener nuestro código lo más simple posible. La complejidad innecesaria aumenta el riesgo de errores y dificulta el mantenimiento.

Ejemplo en ReactJS

Incorrecto:

function UserProfile({ user }) {
  const renderUserProfile = () => {
    if (user && user.name && user.age && user.location) {
      return (
        <div>
          <h1>{user.name}</h1>
          <p>Age: {user.age}</p>
          <p>Location: {user.location}</p>
        </div>
      );
    } else {
      return <p>No user data available.</p>;
    }
  };

  return (
    <div>
      {renderUserProfile()}
    </div>
  );
}

Correcto:

function UserProfile({ user }) {
  if (!user) return <p>No user data available.</p>;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Age: {user.age}</p>
      <p>Location: {user.location}</p>
    </div>
  );
}

2. DRY (Don’t Repeat Yourself)

Principio

DRY se refiere a la necesidad de evitar la duplicación de código. El código duplicado es difícil de mantener porque cualquier cambio debe hacerse en múltiples lugares.

Ejemplo en ReactJS

Incorrecto:

function Header() {
  return <h1 style=>Welcome to My Site</h1>;
}

function Footer() {
  return <h1 style=>Thank you for visiting!</h1>;
}

Correcto:

const headingStyle = { color: 'blue', fontSize: '24px' };

function Header() {
  return <h1 style={headingStyle}>Welcome to My Site</h1>;
}

function Footer() {
  return <h1 style={headingStyle}>Thank you for visiting!</h1>;
}

3. SOLID

Principio

Los principios SOLID son un conjunto de cinco principios que promueven un diseño de software robusto y mantenible.

  1. Single Responsibility Principle (SRP): Una clase debe tener una única responsabilidad.
  2. Open/Closed Principle (OCP): Las clases deben estar abiertas para extensión, pero cerradas para modificación.
  3. Liskov Substitution Principle (LSP): Las clases derivadas deben poder sustituir a sus clases base.
  4. Interface Segregation Principle (ISP): Los clientes no deberían estar obligados a depender de interfaces que no utilizan.
  5. Dependency Inversion Principle (DIP): Las clases de alto nivel no deberían depender de clases de bajo nivel. Ambas deben depender de abstracciones.

Ejemplo en ReactJS: Open/Closed Principle (OCP)

Incorrecto:

function calculateDiscount(type, amount) {
  if (type === 'student') {
    return amount * 0.8;
  } else if (type === 'veteran') {
    return amount * 0.7;
  } else {
    return amount;
  }
}

Correcto:

function calculateDiscount(discountStrategy, amount) {
  return discountStrategy.calculate(amount);
}

class StudentDiscount {
  calculate(amount) {
    return amount * 0.8;
  }
}

class VeteranDiscount {
  calculate(amount) {
    return amount * 0.7;
  }
}

// Uso
const discount = new StudentDiscount();
const total = calculateDiscount(discount, 100);

Ejemplo en ReactJS: Liskov Substitution Principle (LSP)

Incorrecto:

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  setWidth(width) {
    this.width = width;
  }

  setHeight(height) {
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }
}

class Square extends Rectangle {
  setWidth(width) {
    this.width = width;
    this.height = width;  // Rompe el principio LSP
  }

  setHeight(height) {
    this.height = height;
    this.width = height;  // Rompe el principio LSP
  }
}

Correcto:

class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  area() {
    return this.width * this.height;
  }
}

class Square {
  constructor(size) {
    this.size = size;
  }

  area() {
    return this.size * this.size;
  }
}

// Ahora ambas clases pueden ser utilizadas de manera independiente sin romper el LSP

Ejemplo en ReactJS: Interface Segregation Principle (ISP)

Incorrecto:

class User {
  getDetails() {
    // Obtener detalles del usuario
  }

  getAddress() {
    // Obtener dirección del usuario
  }

  getPaymentHistory() {
    // Obtener historial de pagos
  }
}

function getUserPaymentHistory(user) {
  return user.getPaymentHistory();
}

Correcto:

class UserDetails {
  getDetails() {
    // Obtener detalles del usuario
  }
}

class UserAddress {
  getAddress() {
    // Obtener dirección del usuario
  }
}

class UserPaymentHistory {
  getPaymentHistory() {
    // Obtener historial de pagos
  }
}

function getUserPaymentHistory(paymentHistory) {
  return paymentHistory.getPaymentHistory();
}

Ejemplo en ReactJS: Dependency Inversion Principle (DIP)

Incorrecto:

class MySQLDatabase {
  connect() {
    // Lógica para conectarse a una base de datos MySQL
  }
}

class UserService {
  constructor() {
    this.db = new MySQLDatabase();  // Alto acoplamiento a una implementación específica
  }

  getUser(id) {
    this.db.connect();
    // Lógica para obtener el usuario
  }
}

Correcto:

class MySQLDatabase {
  connect() {
    // Lógica para conectarse a una base de datos MySQL
  }
}

class UserService {
  constructor(database) {
    this.db = database;  // Depende de una abstracción (base de datos), no de una implementación específica
  }

  getUser(id) {
    this.db.connect();
    // Lógica para obtener el usuario
  }
}

// Uso
const db = new MySQLDatabase();
const userService = new UserService(db);

4. YAGNI (You Aren’t Gonna Need It)

Principio

YAGNI es un principio que nos recuerda que no debemos agregar funcionalidades “por si acaso” las necesitamos en el futuro. Solo deberíamos implementar lo que se necesita ahora.

Ejemplo en ReactJS

Incorrecto:

function UserProfile({ user }) {
  const [theme, setTheme] = useState('light'); // ¿Realmente necesitamos un tema aquí?

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Age: {user.age}</p>
      <p>Location: {user.location}</p>
    </div>
  );
}

Correcto:

function UserProfile({ user }) {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>Age: {user.age}</p>
      <p>Location: {user.location}</p>
    </div>
  );
}

Aplicar estos principios en tus proyectos de ReactJS o cualquier otro leguaje te ayudará a mantener un código más limpio, fácil de entender y de mantener. Recuerda siempre mantener las cosas simples, evitar la duplicación, seguir los principios SOLID y no implementar funcionalidades innecesarias.