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
Navigable website
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.
npm install
npm run devValidation
npm run build
npm run test
npm run test:e2e
npm run verify:content
npm run check:linksnpm 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:contentandnpm run check:links; runnpm run check:links -- --fetchto verify that reference websites respond. - Project skills are available in
.claude/skills/:create-contentfor new guide pages,create-commitfor focused Conventional Commits, andcreate-prfor preparing draft pull requests.
Índice
- Guía para entrevistas técnicas como Ingeniero de software
- Índice
- Buenas prácticas
- Buenas prácticas en...
- Algoritmos y estructuras de datos
- Visualizar algoritmos
- Visualgo
- Patrones de diseño
- Diseño de sistemas
- Bases de datos
- Arquitectura de Software
- Preguntas más frecuentes
- Control de Versiones
- CI/CD
- Contenedores y Orquestación
- IA para desarrolladores
- Authors
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
Data Structures using C | What are the Data Structure in C and How it works?
Top Data Structures & Algorithms in Java That You Need to Know
Discovering PHP Data Structures: Arrays, Linked Lists, and Binary Trees
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
- System Design Questions + Solutions DB
- System-design-interview
- System Design Interview Questions and Answers [2025]
- A Beginner’s Guide to System Design
- 11 Most-Asked System Design Interview Questions (+ answers)
- Top 50 System Design Interview Questions for 2025
- System Design Interview Questions
- System Design CheatSheet for Interview
Bases de datos
ORM's
Arquitectura de Software
Frontend
A Comprehensive Guide to Modern Frontend Architecture Patterns
Alejándonos de ReactJs y VueJs en frontend usando Clean Architecture
Introducción a la arquitectura de microfrontends con un ejemplo en React.
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
- The Ultimate List of AI Concepts in AI for Absolute Beginners | And Let Me Know What You Want to Read About Next
- 25 Essential AI Concepts Every AI Developer Must Master
- Awesome AI-Powered Developer Tools
- Best AI tools for developers to use in your next coding project
- What is MCP? A Beginner’s Guide to Smarter AI
- Understanding Model Context Protocol (MCP): A Beginner’s Guide
- MCP Introduction
- MCP for beginners by Microsoft
Authors
2. In-Tree Documentation Chapters (DevCaress/guia-entrevistas-de-programacion)
File: README.md
Guía para entrevistas técnicas como Ingeniero de software
Navigable website
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.
npm install
npm run devValidation
npm run build
npm run test
npm run test:e2e
npm run verify:content
npm run check:linksnpm 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:contentandnpm run check:links; runnpm run check:links -- --fetchto verify that reference websites respond. - Project skills are available in
.claude/skills/:create-contentfor new guide pages,create-commitfor focused Conventional Commits, andcreate-prfor preparing draft pull requests.
Índice
- Guía para entrevistas técnicas como Ingeniero de software
- Índice
- Buenas prácticas
- Buenas prácticas en...
- Algoritmos y estructuras de datos
- Visualizar algoritmos
- Visualgo
- Patrones de diseño
- Diseño de sistemas
- Bases de datos
- Arquitectura de Software
- Preguntas más frecuentes
- Control de Versiones
- CI/CD
- Contenedores y Orquestación
- IA para desarrolladores
- Authors
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
Data Structures using C | What are the Data Structure in C and How it works?
Top Data Structures & Algorithms in Java That You Need to Know
Discovering PHP Data Structures: Arrays, Linked Lists, and Binary Trees
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
- System Design Questions + Solutions DB
- System-design-interview
- System Design Interview Questions and Answers [2025]
- A Beginner’s Guide to System Design
- 11 Most-Asked System Design Interview Questions (+ answers)
- Top 50 System Design Interview Questions for 2025
- System Design Interview Questions
- System Design CheatSheet for Interview
Bases de datos
ORM's
Arquitectura de Software
Frontend
A Comprehensive Guide to Modern Frontend Architecture Patterns
Alejándonos de ReactJs y VueJs en frontend usando Clean Architecture
Introducción a la arquitectura de microfrontends con un ejemplo en React.
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
- The Ultimate List of AI Concepts in AI for Absolute Beginners | And Let Me Know What You Want to Read About Next
- 25 Essential AI Concepts Every AI Developer Must Master
- Awesome AI-Powered Developer Tools
- Best AI tools for developers to use in your next coding project
- What is MCP? A Beginner’s Guide to Smarter AI
- Understanding Model Context Protocol (MCP): A Beginner’s Guide
- MCP Introduction
- MCP for beginners by Microsoft
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:
- label: "Algoritmos en C"
url: "https://github.com/TheAlgorithms/C" - label: "Algoritmos en C++"
url: "https://github.com/TheAlgorithms/C-Plus-Plus" - label: "Algoritmos en Go"
url: "https://github.com/TheAlgorithms/Go" - label: "Algoritmos en Java"
url: "https://github.com/TheAlgorithms/Java" - label: "Algoritmos en Javascript"
url: "https://github.com/TheAlgorithms/JavaScript" - label: "Algoritmos en PHP"
url: "https://github.com/TheAlgorithms/PHP" - label: "Algoritmos en Python"
url: "https://github.com/TheAlgorithms/Python" - label: "Algoritmos en Typescript"
url: "https://github.com/TheAlgorithms/TypeScript"
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:
- label: "¿Qué es la complejidad algorítmica y con qué se come?"
url: "https://medium.com/@joseguillermo_/qué-es-la-complejidad-algorítmica-y-con-qué-se-come-2638e7fd9e8c" - label: "Introducción a Big-O Notation"
url: "https://medium.com/nowports-tech/introducción-a-big-o-notation-95ecca8bd866" - label: "Analysis of Algorithms | Big-O analysis"
url: "https://www.geeksforgeeks.org/analysis-algorithms-big-o-analysis/" - label: "Big-O Cheat Sheet"
url: "https://www.bigocheatsheet.com/" - label: "freeCodeCamp — Big O Notation"
url: "https://www.freecodecamp.org/news/big-o-notation-why-it-matters-and-why-it-doesnt-1674cfa8a23c/" - label: "Khan Academy — Asymptotic notation"
url: "https://www.khanacademy.org/computing/computer-science/algorithms/asymptotic-notation/a/asymptotic-notation" - label: "GeeksforGeeks — Time Complexity and Space Complexity"
url: "https://www.geeksforgeeks.org/time-complexity-and-space-complexity/" - label: "MDN — Algorithm (Glossary)"
url: "https://developer.mozilla.org/en-US/docs/Glossary/Algorithm" - label: "Introduction to Algorithms (CLRS), MIT Press"
url: "https://mitpress.mit.edu/9780262046305/introduction-to-algorithms/" - label: "VisuAlgo — Visualizacion de algoritmos"
url: "https://visualgo.net/en"
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
ngrande el termino cuadratico domina a todos los demas.
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.
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).
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.
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).
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.
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).
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.
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}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.
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.
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.
function sumTo(n) {
if (n === 0) return 0;
return n + sumTo(n - 1);
}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.
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:
- label: "Data Structures using C | What are the Data Structure in C and How it works?"
url: "https://www.mygreatlearning.com/blog/data-structures-using-c/" - label: "C++'s Built-In Data Structures"
url: "https://www.codecademy.com/learn/c-plus-plus-for-programmers/modules/cpp-built-in-data-structures/cheatsheet" - label: "Top Data Structures & Algorithms in Java That You Need to Know"
url: "https://medium.com/edureka/data-structures-algorithms-in-java-d27e915db1c5" - label: "JavaScript Algorithms and Data Structures"
url: "https://github.com/trekhleb/javascript-algorithms" - label: "Discovering PHP Data Structures: Arrays, Linked Lists, and Binary Trees"
url: "https://medium.com/@london.lingo.01/discovering-php-data-structures-arrays-linked-lists-and-binary-trees-501566f83bad" - label: "Efficient data structures for PHP 7"
url: "https://medium.com/@rtheunissen/efficient-data-structures-for-php-7-9dda7af674cd" - label: "Python Data Structures"
url: "https://www.geeksforgeeks.org/python-data-structures/"
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:
- label: "CodeWars"
url: "https://www.codewars.com/" - label: "LeetCode"
url: "https://leetcode.com" - label: "HackerRank"
url: "https://www.hackerrank.com/" - label: "CoderByte"
url: "https://coderbyte.com/" - label: "Exercism"
url: "https://exercism.org/"
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:
- label: "Visualgo"
url: "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
File: src/content/guide/buenas-practicas/clean-architecture.mdx
title: "Clean Architecture"
category: "Buenas practicas"
section: "Arquitectura"
sidebar:
label: "Clean Architecture"
order: 40
references:
- label: "The Clean Architecture — Robert C. Martin (blog original)"
url: "https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" - label: "Clean Architecture: A Craftsman's Guide to Software Structure and Design"
url: "https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/" - label: "The Dependency Rule explained"
url: "https://khalilstemmler.com/wiki/dependency-rule/"
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:
- Entities — reglas de negocio globales de la aplicacion (objetos y logica que existirian aunque cambiaras de framework o de base de datos).
- Use Cases — reglas de negocio especificas de la aplicacion; orquestan las entities para cumplir un caso de uso concreto.
- Interface Adapters — controladores, presenters y gateways que traducen datos entre los use cases y el mundo exterior (HTTP, CLI, etc.).
- 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
// 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
// --- 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
UserServiceno 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:
- label: "Clean Code en Java - Español"
url: "https://github.com/alansastre/java-clean-code" - label: "Clean Code en Java - Inglés"
url: "https://github.com/JuanCrg90/Clean-Code-Notes" - label: "Clean Code en Javascript - Español"
url: "https://github.com/andersontr15/clean-code-javascript-es" - label: "Clean Code en Javascript - Inglés"
url: "https://github.com/ryanmcdermott/clean-code-javascript#openclosed-principle-ocp" - label: "Clean Code en Python - Español"
url: "https://github.com/sryvcr/clean-code-python-es" - label: "Clean Code en Python - Inglés"
url: "https://github.com/zedr/clean-code-python"
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:
- label: "Demystifying Software Development Principles: DRY, KISS, YAGNI, SOLID, GRASP, and LoD"
url: "https://levelup.gitconnected.com/demystifying-software-development-principles-dry-kiss-yagni-solid-grasp-and-lod-8606113c0313" - label: "The Pragmatic Programmer — DRY Principle"
url: "https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/" - label: "DRY: Don't Repeat Yourself — refactoring.guru"
url: "https://refactoring.guru/extract-method"
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
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
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:
- label: "Applying UML and Patterns — Craig Larman"
url: "https://www.pearson.com/en-us/subject-catalog/p/applying-uml-and-patterns-an-introduction-to-object-oriented-analysis-and-design-and-iterative-development/P200000009412" - label: "GRASP Patterns — Wikipedia"
url: "https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)"
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:
- Experto en Informacion — asigna la responsabilidad a la clase que tiene la informacion necesaria para cumplirla.
- Creador — la clase B debe crear instancias de A si B contiene, agrega o registra objetos A.
- Controlador — un objeto no-UI coordina los casos de uso del sistema.
- Bajo Acoplamiento — minimiza las dependencias entre clases para facilitar el cambio.
- Alta Cohesion — cada clase tiene responsabilidades fuertemente relacionadas entre si.
- Polimorfismo — usa polimorfismo en lugar de condicionales para manejar variaciones de comportamiento.
- Indireccion — introduce un intermediario para desacoplar componentes.
- Fabricacion Pura — crea una clase artificial para mantener alta cohesion y bajo acoplamiento.
- Variaciones Protegidas — encapsula los puntos de variacion para que los cambios no se propaguen.
Ejemplo: Experto en Informacion
// 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()); // 117Order concentra toda la logica sobre su propio estado. OrderService queda libre de conocer la estructura interna de los items.
--- METRICS ---
- Files Extracted: 11
- Estimated Token Budget: ~19471 tokens
- Recency Window: Active (< 180 days)
- Canonical Reference: https://codewiki.google/github.com/DevCaress/guia-entrevistas-de-programacion