guia-entrevistas-de-programacion

Documentation and developer resources for DevCaress/guia-entrevistas-de-programacion

7,881 stars Unknown 11 files · ~19,605 tokens
RAW Doc

Technical Documentation: DevCaress/guia-entrevistas-de-programacion

ℹ️ Provenance: Hybrid Fusion: DevCaress/guia-entrevistas-de-programacion (README + 10 In-Tree Chapters) · CodeWiki Reference · Recency: Active (< 180 days)

1. Project Overview & Quickstart (DevCaress/guia-entrevistas-de-programacion)

Guía para entrevistas técnicas como Ingeniero de software

This guide is now published as an Astro static site. The README preserves the historical index, while the browsable content lives in src/content/guide/**/*.mdx.

Visit the guide at caress.dev/guia.

Local development

Use Node.js >=22.12.0.

bash
npm install
npm run dev

Validation

bash
npm run build
npm run test
npm run test:e2e
npm run verify:content
npm run check:links

npm run verify:content compares the README sections and references against the migrated MDX files. npm run check:links validates URL syntax; to verify external availability over the network, run npm run check:links -- --fetch.

Add content

Each new section must be added as an .mdx file in src/content/guide/ and include title, description, category, sidebar.order and references. Original references should be defined in the frontmatter, while custom examples can be added using examples or as MDX code blocks within the content.

Contributing

Contributions are welcome. Read CONTRIBUTING.md for the local setup, branch and commit conventions, content rules, and required validation.

  • Suggest a new topic or resource with the content suggestion issue template, or report a problem with the bug report template.
  • Open focused pull requests using the PR template. Link the related issue with Closes # when applicable.
  • For content changes, run npm run verify:content and npm run check:links; run npm run check:links -- --fetch to verify that reference websites respond.
  • Project skills are available in .claude/skills/: create-content for new guide pages, create-commit for focused Conventional Commits, and create-pr for preparing draft pull requests.

Índice

Buenas prácticas

Principios SOLID


DRY


Clean Code


Clean architecture

Buenas prácticas en:

Angular

C++

Dart

Django

Flutter

Java

Javascript

PHP

Python

React.js

Typescript

Vue.js

Algoritmos y estructuras de datos

Complejidad algorítmica

Algoritmos

Estructuras de datos

Practicar algoritmos y estructuras de datos

Visualizar algoritmos

[Visualgo](https://visualgo.net/)

En esta web podrás ver como funcionan de manera visual los siguientes algoritmos:

  • Sorting
    • Bubble Sort
    • Selection Sort
    • Insertion Sort
    • Merge Sort
    • Quick Sort
    • Random Quick Sort
    • Counting Sort
    • Radix Sort
  • Linked List
    • Stack
    • Queue
    • Doubly Linked List
    • Deque
  • Hash Tables
    • Linear Probing
    • Quadratic Probing
    • Double Hashing
    • Separate Chaining
  • Binary Heap
  • Binary Search Tree
    • AVL Tree

Patrones de diseño

Patrones de diseño Español (Recomendación personal)

Patrones de diseño en Javascript

  • Patrones Creacionales
    • Singleton
    • Factory Method
    • Abstract Factory
    • Builder
    • Prototype
  • Patrones Estructurales
    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  • Patrones de comportamiento
    • Chain of Responsibility
    • Command
    • Iterator
    • Mediator
    • Memento
    • Observer
    • State
    • Strategy
    • Template Method
    • Interpreter
    • Visitor

Diseño de sistemas

Bases de datos

ORM's

Arquitectura de Software

Frontend

React Clean Architecture

Vue JS Clean Architecture

Backend

Clean Architecture Express JS

Clean Architecture Java

Clean Architecture PHP

Clean Architecture Python

Preguntas más frecuentes

Preguntas de Frontend

Preguntas de Backend

Control de Versiones

Workflows

CI/CD

Contenedores y Orquestación

IA para desarrolladores

Authors

2. In-Tree Documentation Chapters (DevCaress/guia-entrevistas-de-programacion)

File: README.md

Guía para entrevistas técnicas como Ingeniero de software

This guide is now published as an Astro static site. The README preserves the historical index, while the browsable content lives in src/content/guide/**/*.mdx.

Visit the guide at caress.dev/guia.

Local development

Use Node.js >=22.12.0.

bash
npm install
npm run dev

Validation

bash
npm run build
npm run test
npm run test:e2e
npm run verify:content
npm run check:links

npm run verify:content compares the README sections and references against the migrated MDX files. npm run check:links validates URL syntax; to verify external availability over the network, run npm run check:links -- --fetch.

Add content

Each new section must be added as an .mdx file in src/content/guide/ and include title, description, category, sidebar.order and references. Original references should be defined in the frontmatter, while custom examples can be added using examples or as MDX code blocks within the content.

Contributing

Contributions are welcome. Read CONTRIBUTING.md for the local setup, branch and commit conventions, content rules, and required validation.

  • Suggest a new topic or resource with the content suggestion issue template, or report a problem with the bug report template.
  • Open focused pull requests using the PR template. Link the related issue with Closes # when applicable.
  • For content changes, run npm run verify:content and npm run check:links; run npm run check:links -- --fetch to verify that reference websites respond.
  • Project skills are available in .claude/skills/: create-content for new guide pages, create-commit for focused Conventional Commits, and create-pr for preparing draft pull requests.

Índice

Buenas prácticas

Principios SOLID


DRY


Clean Code


Clean architecture

Buenas prácticas en:

Angular

C++

Dart

Django

Flutter

Java

Javascript

PHP

Python

React.js

Typescript

Vue.js

Algoritmos y estructuras de datos

Complejidad algorítmica

Algoritmos

Estructuras de datos

Practicar algoritmos y estructuras de datos

Visualizar algoritmos

[Visualgo](https://visualgo.net/)

En esta web podrás ver como funcionan de manera visual los siguientes algoritmos:

  • Sorting
    • Bubble Sort
    • Selection Sort
    • Insertion Sort
    • Merge Sort
    • Quick Sort
    • Random Quick Sort
    • Counting Sort
    • Radix Sort
  • Linked List
    • Stack
    • Queue
    • Doubly Linked List
    • Deque
  • Hash Tables
    • Linear Probing
    • Quadratic Probing
    • Double Hashing
    • Separate Chaining
  • Binary Heap
  • Binary Search Tree
    • AVL Tree

Patrones de diseño

Patrones de diseño Español (Recomendación personal)

Patrones de diseño en Javascript

  • Patrones Creacionales
    • Singleton
    • Factory Method
    • Abstract Factory
    • Builder
    • Prototype
  • Patrones Estructurales
    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  • Patrones de comportamiento
    • Chain of Responsibility
    • Command
    • Iterator
    • Mediator
    • Memento
    • Observer
    • State
    • Strategy
    • Template Method
    • Interpreter
    • Visitor

Diseño de sistemas

Bases de datos

ORM's

Arquitectura de Software

Frontend

React Clean Architecture

Vue JS Clean Architecture

Backend

Clean Architecture Express JS

Clean Architecture Java

Clean Architecture PHP

Clean Architecture Python

Preguntas más frecuentes

Preguntas de Frontend

Preguntas de Backend

Control de Versiones

Workflows

CI/CD

Contenedores y Orquestación

IA para desarrolladores

Authors


File: src/content/guide/algoritmos-y-estructuras-de-datos/algoritmos.mdx


title: "Algoritmos"
category: "Algoritmos y estructuras de datos"
section: "Fundamentos"
sidebar:
label: "Algoritmos"
order: 320
references:


Esta seccion reune recursos y criterios de estudio sobre Algoritmos. Usa las referencias para profundizar y agrega ejemplos propios conforme avance la guia.


File: src/content/guide/algoritmos-y-estructuras-de-datos/complejidad-algoritmica.mdx


title: "Complejidad algoritmica"
category: "Algoritmos y estructuras de datos"
section: "Fundamentos"
sidebar:
label: "Complejidad algoritmica"
order: 310
references:


import Callout from '../../../components/Callout.astro';
import CodeExample from '../../../components/CodeExample.astro';

La complejidad algoritmica mide como crece el consumo de recursos de un algoritmo (tiempo de ejecucion y memoria) a medida que aumenta el tamano de la entrada, que solemos llamar n. No nos dice cuantos segundos tarda un programa en una maquina concreta, sino como se comporta cuando los datos crecen: si duplicar la entrada duplica el trabajo, lo cuadruplica o lo dispara sin control.

Entender esto es clave porque te permite comparar dos soluciones sin depender del hardware, del lenguaje ni de micro-optimizaciones, y anticipar si un algoritmo seguira siendo viable con un millon de elementos. Es uno de los temas mas preguntados en entrevistas tecnicas.

Que medimos: operaciones, no segundos

El tiempo de reloj depende de la CPU, del lenguaje, de la carga del sistema y hasta del compilador. Por eso, en lugar de medir segundos, contamos operaciones basicas (comparaciones, asignaciones, accesos) en funcion de n. Lo que nos interesa es la tasa de crecimiento: como escala ese conteo cuando n se vuelve grande.

Por ejemplo, recorrer una lista de n elementos hace del orden de n operaciones. Que cada iteracion cueste 3 o 5 instrucciones internas no cambia la idea central: el trabajo crece de forma proporcional a n.

Notacion Big-O

Big-O describe la cota superior asintotica de un algoritmo: cuanto crece su costo en el peor caso cuando n tiende a infinito. Escribimos O(n), O(n^2), O(log n), etc. Para obtener el Big-O de un algoritmo se aplican dos reglas practicas:

  • Se ignoran las constantes: O(2n) se simplifica a O(n), y O(n / 2) tambien es O(n). Las constantes no cambian la forma de la curva.
  • Se conserva solo el termino dominante: O(n^2 + n + 100) se simplifica a O(n^2), porque para n grande el termino cuadratico domina a todos los demas.
Big-O (O) es la cota superior (peor caso). Big-Omega (Ω) es la cota inferior (mejor caso) y Big-Theta (Θ) es la cota ajustada, cuando el mejor y el peor caso crecen igual. En la practica y en entrevistas casi siempre se habla de Big-O, asumiendo el peor caso.

Grafico de tasas de crecimiento

Este grafico compara como escalan las complejidades mas comunes. Mientras mas empinada es la curva, peor escala el algoritmo cuando crece la entrada n.

Operaciones Tamano de la entrada (n)

O(1)

O(log n)

O(n)

O(n log n)

O(n^2)

O(2^n)

La siguiente tabla vuelve tangible esa diferencia: muestra el numero aproximado de operaciones para distintos tamanos de entrada.

Notacion Nombre n = 10 n = 100 n = 1000
O(1) Constante 1 1 1
O(log n) Logaritmica 3 7 10
O(n) Lineal 10 100 1000
O(n log n) Linealitmica 33 664 9966
O(n^2) Cuadratica 100 10 000 1 000 000
O(2^n) Exponencial 1024 ~1.3 x 10^30 enorme

Complejidad temporal (tiempo)

La complejidad temporal describe como crece el numero de operaciones en funcion de n. Estas son las clases mas comunes, de la mejor a la peor.

O(1) — Constante

El costo no depende del tamano de la entrada: siempre hace la misma cantidad de trabajo. Acceder a un indice de un array o leer una clave de un objeto o Map es O(1).

js
function firstElement(items) {
  return items[0];
}

O(log n) — Logaritmica

En cada paso se descarta la mitad de los datos, asi que el numero de pasos crece muy lentamente. El ejemplo clasico es la busqueda binaria sobre un array ordenado.

js
function binarySearch(sortedItems, target) {
  let low = 0;
  let high = sortedItems.length - 1;

  while (low <= high) {
    const mid = Math.floor((low + high) / 2);
    if (sortedItems[mid] === target) return mid;
    if (sortedItems[mid] < target) low = mid + 1;
    else high = mid - 1;
  }

  return -1;
}

O(n) — Lineal

El trabajo crece de forma proporcional a n: un solo recorrido de la entrada. Buscar el maximo de una lista es O(n).

js
function findMax(numbers) {
  let max = numbers[0];
  for (const value of numbers) {
    if (value > max) max = value;
  }
  return max;
}

O(n log n) — Linealitmica

Es el mejor costo posible para ordenar por comparaciones. Algoritmos como merge sort o el sort nativo del lenguaje son O(n log n): hacen log n niveles de division y n trabajo en cada nivel.

js
function sortAscending(numbers) {
  return [...numbers].sort((a, b) => a - b);
}

O(n^2) — Cuadratica

Aparece con bucles anidados que recorren la entrada dentro de otro recorrido de la entrada. Comparar cada elemento con todos los demas para buscar duplicados de forma ingenua es O(n^2).

js
function hasDuplicate(items) {
  for (let i = 0; i < items.length; i++) {
    for (let j = i + 1; j < items.length; j++) {
      if (items[i] === items[j]) return true;
    }
  }
  return false;
}

O(2^n) — Exponencial

El costo se duplica con cada elemento adicional. La version recursiva ingenua de Fibonacci recalcula los mismos valores una y otra vez, generando un arbol de llamadas que crece exponencialmente. Es inviable incluso para entradas moderadas.

js
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}
La complejidad factorial O(n!) es aun peor que la exponencial. Aparece al generar todas las permutaciones de una entrada o en soluciones de fuerza bruta al problema del viajante. Con solo 15 elementos ya supera el billon de operaciones.

Complejidad espacial (memoria)

La complejidad espacial mide cuanta memoria adicional necesita un algoritmo mas alla de la entrada. Se suele reportar el espacio auxiliar: las estructuras nuevas que creas, mas la memoria del stack por la recursion. La entrada en si no siempre se cuenta.

O(1) espacio

El algoritmo usa una cantidad fija de memoria extra sin importar el tamano de la entrada, tipicamente unas pocas variables.

js
function sum(numbers) {
  let total = 0;
  for (const value of numbers) {
    total += value;
  }
  return total;
}

O(n) espacio

La memoria extra crece con la entrada, por ejemplo al construir una nueva estructura del tamano de n.

js
function double(numbers) {
  const result = [];
  for (const value of numbers) {
    result.push(value * 2);
  }
  return result;
}

La recursion tambien cuesta memoria

Cada llamada recursiva pendiente ocupa un marco en el call stack. Una recursion lineal como la siguiente usa O(n) de memoria en el stack, aunque no cree ninguna estructura de datos explicita.

js
function sumTo(n) {
  if (n === 0) return 0;
  return n + sumTo(n - 1);
}
A menudo se puede cambiar tiempo por memoria y viceversa. La memoizacion, por ejemplo, guarda resultados ya calculados en una tabla: convierte el Fibonacci exponencial O(2^n) en uno lineal O(n) en tiempo, a costa de O(n) de memoria. Elegir el balance correcto depende del problema y de las restricciones.

Mejor, peor y caso promedio

Un mismo algoritmo puede comportarse distinto segun la entrada concreta. Tomemos una busqueda lineal:

  • Mejor caso — el elemento buscado esta en la primera posicion: O(1).
  • Peor caso — el elemento esta al final o no existe: O(n).
  • Caso promedio — en promedio se recorre la mitad de la lista: O(n).

Cuando alguien dice "la complejidad de este algoritmo es O(n)" casi siempre se refiere al peor caso, porque es la garantia mas util: nos dice que tan mal puede ir como maximo.

Como analizar tu codigo

Algunas reglas practicas para estimar el Big-O de un fragmento de codigo:

  • Bucle simple sobre la entrada: O(n).
  • Bucles anidados sobre la entrada: se multiplican, dos niveles dan O(n^2).
  • Dividir el problema a la mitad en cada paso: aparece un factor log n (como en la busqueda binaria).
  • Operaciones consecutivas: se suman y luego se conserva el termino dominante (O(n) + O(n^2) es O(n^2)).
  • Recursion: dibuja el arbol de llamadas; su tamano total es la complejidad temporal, y su profundidad, el costo de memoria en el stack.
Indica siempre la complejidad de tiempo y de espacio de tu solucion, y aclara que estas describiendo el peor caso. Si tu primer enfoque es O(n^2), menciona en voz alta si existe una version O(n log n) o O(n) usando una estructura auxiliar como un hash set. Justificar el analisis suele valer tanto como llegar a la respuesta.

File: src/content/guide/algoritmos-y-estructuras-de-datos/estructuras-de-datos.mdx


title: "Estructuras de datos"
category: "Algoritmos y estructuras de datos"
section: "Fundamentos"
sidebar:
label: "Estructuras de datos"
order: 330
references:


Esta seccion reune recursos y criterios de estudio sobre Estructuras de datos. Usa las referencias para profundizar y agrega ejemplos propios conforme avance la guia.


File: src/content/guide/algoritmos-y-estructuras-de-datos/practicar-algoritmos.mdx


title: "Practicar algoritmos"
category: "Algoritmos y estructuras de datos"
section: "Practica"
sidebar:
label: "Practicar algoritmos"
order: 340
references:


Esta seccion reune recursos y criterios de estudio sobre Practicar algoritmos. Usa las referencias para profundizar y agrega ejemplos propios conforme avance la guia.


File: src/content/guide/algoritmos-y-estructuras-de-datos/visualgo.mdx


title: "Visualgo"
category: "Algoritmos y estructuras de datos"
section: "Visualizacion"
sidebar:
label: "Visualgo"
order: 350
references:


En esta web podrás ver como funcionan de manera visual los siguientes algoritmos:

  • Sorting
    • Bubble Sort
    • Selection Sort
    • Insertion Sort
    • Merge Sort
    • Quick Sort
    • Random Quick Sort
    • Counting Sort
    • Radix Sort
  • Linked List
    • Stack
    • Queue
    • Doubly Linked List
    • Deque
  • Hash Tables
    • Linear Probing
    • Quadratic Probing
    • Double Hashing
    • Separate Chaining
  • Binary Heap
  • Binary Search Tree
    • AVL Tree

File: src/content/guide/buenas-practicas/clean-architecture.mdx


title: "Clean Architecture"
category: "Buenas practicas"
section: "Arquitectura"
sidebar:
label: "Clean Architecture"
order: 40
references:


Clean Architecture es una propuesta de Robert C. Martin (Uncle Bob) para organizar el codigo en capas concentricas, de forma que la logica de negocio quede aislada de detalles como el framework web, la base de datos o la UI. No es un framework ni una libreria: es un conjunto de reglas sobre hacia donde pueden apuntar las dependencias.


Las capas

De adentro hacia afuera:

  1. Entities — reglas de negocio globales de la aplicacion (objetos y logica que existirian aunque cambiaras de framework o de base de datos).
  2. Use Cases — reglas de negocio especificas de la aplicacion; orquestan las entities para cumplir un caso de uso concreto.
  3. Interface Adapters — controladores, presenters y gateways que traducen datos entre los use cases y el mundo exterior (HTTP, CLI, etc.).
  4. Frameworks & Drivers — la capa mas externa: framework web, ORM, driver de base de datos, UI. Aqui vive todo lo que es "detalle", no negocio.

La regla de dependencia

Las dependencias del codigo fuente solo pueden apuntar hacia adentro.

Una capa interna nunca debe conocer nada de una capa externa. Las Entities no saben que existe una base de datos; los Use Cases no saben si los datos llegan por HTTP o por CLI. Cuando una capa interna necesita algo de afuera (por ejemplo, persistir datos), define una interfaz (puerto) en su propia capa, y la capa externa la implementa. Esto se apoya en el Dependency Inversion Principle (la "D" de SOLID).

Violacion de la regla

js
// El caso de uso depende directamente de un detalle: el ORM y el framework HTTP
const UserModel = require("../infra/orm/UserModel"); // Sequelize

class RegisterUserUseCase {
  async execute(req, res) {
    // logica de negocio mezclada con validacion HTTP y con el ORM
    if (!req.body.email.includes("@")) {
      return res.status(400).json({ error: "email invalido" });
    }

    const user = await UserModel.create({ email: req.body.email });
    return res.status(201).json(user);
  }
}

Este caso de uso no se puede probar sin levantar Express ni sin una base de datos real, y no se puede reutilizar si mañana el registro llega por un job en background en vez de HTTP.

Aplicando Clean Architecture

js
// --- Entities: reglas de negocio puras, sin dependencias externas ---
class User {
  constructor(email) {
    if (!email.includes("@")) {
      throw new Error("email invalido");
    }
    this.email = email;
  }
}

// --- Use Cases: define el puerto que necesita, no la implementacion ---
// UserRepository es una interfaz (puerto) que vive en esta capa
class RegisterUserUseCase {
  constructor(userRepository) {
    this.userRepository = userRepository; // depende de una abstraccion
  }

  async execute(email) {
    const user = new User(email);
    await this.userRepository.save(user);
    return user;
  }
}

// --- Interface Adapters: implementa el puerto y traduce HTTP <-> caso de uso ---
class SequelizeUserRepository {
  async save(user) {
    await UserModel.create({ email: user.email });
  }
}

class RegisterUserController {
  constructor(registerUserUseCase) {
    this.registerUserUseCase = registerUserUseCase;
  }

  async handle(req, res) {
    try {
      const user = await this.registerUserUseCase.execute(req.body.email);
      return res.status(201).json(user);
    } catch (err) {
      return res.status(400).json({ error: err.message });
    }
  }
}

// --- Frameworks & Drivers: composicion, el unico lugar que conoce Express y Sequelize ---
const useCase = new RegisterUserUseCase(new SequelizeUserRepository());
const controller = new RegisterUserController(useCase);
app.post("/users", (req, res) => controller.handle(req, res));

Ahora RegisterUserUseCase se puede probar con un UserRepository falso en memoria, sin Express ni base de datos real, y SequelizeUserRepository se puede reemplazar por cualquier otra implementacion sin tocar la logica de negocio.

Errores comunes

  • "Capas" que son solo carpetas: crear carpetas entities/, usecases/, adapters/ no basta si el codigo de adentro sigue importando cosas de afuera (por ejemplo, un use case que importa directamente el modelo de Sequelize).
  • Sobre-ingenieria en proyectos pequeños: para un script o un CRUD trivial, el costo de las capas e interfaces puede superar el beneficio. Clean Architecture rinde cuando la logica de negocio es compleja o el proyecto va a vivir mucho tiempo.
  • Confundir Clean Architecture con "usar controladores y servicios": tener un UserService no es Clean Architecture si ese servicio sigue dependiendo directamente de Express o del ORM.

Resumen

  • La regla central es una sola: las dependencias apuntan hacia adentro, nunca hacia afuera.
  • Las capas internas (Entities, Use Cases) definen puertos; las capas externas los implementan.
  • El beneficio principal es poder probar la logica de negocio sin infraestructura real y poder cambiar frameworks o bases de datos sin reescribir el negocio.
  • No es gratis: aplica el nivel de capas segun la complejidad y vida esperada del proyecto.

File: src/content/guide/buenas-practicas/clean-code.mdx


title: "Clean Code"
category: "Buenas practicas"
section: "Calidad de codigo"
sidebar:
label: "Clean Code"
order: 30
references:


Esta seccion reune recursos y criterios de estudio sobre Clean Code. Usa las referencias para profundizar y agrega ejemplos propios conforme avance la guia.


File: src/content/guide/buenas-practicas/dry.mdx


title: "DRY — Don't Repeat Yourself"
category: "Buenas practicas"
section: "Principios"
sidebar:
label: "DRY"
order: 21
references:


DRY significa Don't Repeat Yourself (No te repitas). El principio establece que cada pieza de conocimiento o logica debe tener una unica representacion dentro del sistema. Cuando la misma logica aparece en varios lugares, un cambio de requisito obliga a actualizar todos esos puntos, lo que introduce inconsistencias y errores.

DRY no trata solo de evitar copiar y pegar codigo. Tambien aplica a configuracion, documentacion, esquemas de base de datos y cualquier otra forma de conocimiento duplicado.

Violacion del principio

js
function calculateStandardPrice(price) {
  return price * 1.21;
}

function calculateReducedPrice(price) {
  return price * 1.10;
}

function calculateSuperReducedPrice(price) {
  return price * 1.04;
}

const total1 = calculateStandardPrice(100);
const total2 = calculateReducedPrice(50);

Cada funcion repite la misma logica de multiplicacion. Si la formula cambia (p. ej. redondeo), hay que actualizarla en tres sitios.

Aplicando DRY

js
const VAT_RATES = {
  standard: 1.21,
  reduced: 1.10,
  superReduced: 1.04,
};

function calculatePrice(price, type = "standard") {
  const multiplier = VAT_RATES[type];
  if (!multiplier) throw new Error(`Unknown VAT type: ${type}`);
  return price * multiplier;
}

const total1 = calculatePrice(100, "standard");
const total2 = calculatePrice(50, "reduced");

La logica de calculo existe en un solo lugar. Cambiar las tasas o la formula solo requiere una modificacion.


File: src/content/guide/buenas-practicas/grasp.mdx


title: "GRASP — General Responsibility Assignment Software Patterns"
category: "Buenas practicas"
section: "Principios"
sidebar:
label: "GRASP"
order: 24
references:


GRASP (General Responsibility Assignment Software Patterns) es un conjunto de nueve principios definidos por Craig Larman para guiar como asignar responsabilidades a clases y objetos en el diseno orientado a objetos:

  1. Experto en Informacion — asigna la responsabilidad a la clase que tiene la informacion necesaria para cumplirla.
  2. Creador — la clase B debe crear instancias de A si B contiene, agrega o registra objetos A.
  3. Controlador — un objeto no-UI coordina los casos de uso del sistema.
  4. Bajo Acoplamiento — minimiza las dependencias entre clases para facilitar el cambio.
  5. Alta Cohesion — cada clase tiene responsabilidades fuertemente relacionadas entre si.
  6. Polimorfismo — usa polimorfismo en lugar de condicionales para manejar variaciones de comportamiento.
  7. Indireccion — introduce un intermediario para desacoplar componentes.
  8. Fabricacion Pura — crea una clase artificial para mantener alta cohesion y bajo acoplamiento.
  9. Variaciones Protegidas — encapsula los puntos de variacion para que los cambios no se propaguen.

Ejemplo: Experto en Informacion

js
// Violation — OrderService knows too much about Order's internals
class OrderService {
  calculateTotal(order) {
    return order.items.reduce((sum, item) => sum + item.price * item.qty, 0);
  }

  calculateDiscount(order) {
    const total = this.calculateTotal(order);
    return total > 100 ? total * 0.1 : 0;
  }
}

// Applying Information Expert
// Order owns the data, so it handles the calculations
class Order {
  constructor(items) {
    this.items = items;
  }

  getTotal() {
    return this.items.reduce((sum, item) => sum + item.price * item.qty, 0);
  }

  getDiscount() {
    return this.getTotal() > 100 ? this.getTotal() * 0.1 : 0;
  }

  getFinalPrice() {
    return this.getTotal() - this.getDiscount();
  }
}

const order = new Order([
  { price: 60, qty: 2 },
  { price: 10, qty: 1 },
]);

console.log(order.getFinalPrice()); // 117

Order concentra toda la logica sobre su propio estado. OrderService queda libre de conocer la estructura interna de los items.

--- METRICS ---