Errores Comunes de Desarrolladores Juniors (y Cómo Evitarlos)
Todos los desarrolladores senior fueron juniors en algún momento y cometieron los mismos errores. La diferencia está en aprender de ellos rápidamente. En 2026, con herramientas de IA que pueden generar código instantáneamente, es tentador saltarse los fundamentos, pero esto amplifica muchos de estos errores.
1. Programar sin entender el problema
El error
Comenzar a escribir código inmediatamente sin analizar completamente el requerimiento.
# Junior salta directo a código sin analizar:
def calcular_descuento(precio):
return precio * 0.1 # ¿10% siempre? ¿Diferentes tipos de cliente?
Cómo evitarlo
Antes de escribir código, responda: ¿Qué entradas recibe? ¿Qué salidas produce? ¿Qué casos edge existen? ¿Cuáles son las reglas de negocio?
from enum import Enum
from dataclasses import dataclass
class CustomerType(Enum):
REGULAR = "regular"
PREMIUM = "premium"
@dataclass
class DiscountRule:
customer_type: CustomerType
discount_percentage: float
max_discount: float = float('inf')
class DiscountCalculator:
def __init__(self, rules: list[DiscountRule]):
self.rules = rules
def calculate(self, price: float, customer_type: CustomerType) -> float:
applicable_rules = [r for r in self.rules if r.customer_type == customer_type]
if not applicable_rules:
return 0
discount = price * applicable_rules[0].discount_percentage
return min(discount, applicable_rules[0].max_discount)
2. No manejar errores adecuadamente
El error
Asumir que todo funcionará perfectamente o usar try-catch genérico.
// Error: No manejar casos nulos
function getUser(userId) {
const user = database.find(userId);
return user.name; // ¿Qué pasa si user es null?
}
// Error: Tragar excepciones
try {
paymentGateway.charge(amount);
} catch (error) {
return false; // ¿Por qué falló?
}
Cómo evitarlo
class UserNotFoundError extends Error {
constructor(userId) {
super(`User with ID ${userId} not found`);
this.userId = userId;
}
}
function getUser(userId) {
const user = database.find(userId);
if (!user) {
throw new UserNotFoundError(userId);
}
return user;
}
async function processPayment(amount) {
try {
const result = await paymentGateway.charge(amount);
logger.info(`Payment successful: ${amount}`, { result });
return { success: true, transactionId: result.id };
} catch (error) {
logger.error('Payment failed', { amount, error: error.message });
throw new PaymentError(`Failed to process payment of ${amount}`, error.code);
}
}
3. No escribir código testeable
El error
Crear código tan acoplado que es imposible de probar sin dependencias externas.
public class OrderService {
public void createOrder(OrderRequest request) {
// Acoplado a implementaciones concretas
Database db = new MySQLDatabase();
EmailService email = new GmailService();
Order order = new Order();
db.save(order);
email.send(request.getCustomerEmail(), "Order confirmed");
}
}
Cómo evitarlo
// Código testeable con inyección de dependencias
public class OrderService {
private final IDatabase database;
private final IEmailService emailService;
public OrderService(IDatabase database, IEmailService emailService) {
this.database = database;
this.emailService = emailService;
}
public OrderResult createOrder(OrderRequest request) {
if (!isValidRequest(request)) {
return OrderResult.invalid("Invalid request");
}
Order order = buildOrder(request);
database.save(order);
emailService.send(request.getCustomerEmail(), "Order confirmed");
return OrderResult.success(order);
}
}
// Test ahora es trivial con mocks
@Test
public void testCreateOrder_Success() {
IDatabase mockDb = mock(IDatabase.class);
IEmailService mockEmail = mock(IEmailService.class);
OrderService service = new OrderService(mockDb, mockEmail);
OrderResult result = service.createOrder(validRequest);
assertTrue(result.isSuccess());
verify(mockDb, times(1)).save(any(Order.class));
}
4. Copiar y pegar código sin entender
El error
Tomar código de Stack Overflow o IA sin comprender qué hace o sus riesgos de seguridad.
# Copiado sin entender - PELIGROSO
import pickle
def load_data(filename):
with open(filename, 'rb') as f:
return pickle.load(f) # Vulnerabilidad: ejecución de código arbitrario
user_data = load_data(request.files['upload']) # ¡NUNCA hacer esto!
Cómo evitarlo
Antes de usar código copiado: lea cada línea, busque las funciones en la documentación oficial, identifique riesgos, verifique alternativas y pruebe casos edge.
import json
from pathlib import Path
def load_data(filename: str) -> dict:
"""Carga datos desde archivo JSON de forma segura."""
if not Path(filename).exists():
raise FileNotFoundError(f"File not found: {filename}")
try:
with open(filename, 'r', encoding='utf-8') as f:
return json.load(f)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON in {filename}: {e}")
5. Ignorar convenciones del equipo
El error
Cada desarrollador usa su propio estilo, haciendo el código inconsistente y difícil de mantener.
Cómo evitarlo
Configure herramientas de linting y formateo automático desde el inicio del proyecto:
// .eslintrc.json
{
"extends": ["airbnb-base", "prettier"],
"rules": {
"no-console": "warn",
"no-unused-vars": "error",
"prefer-const": "error"
}
}
# Pre-commit hooks
npm run lint
npm run format
npm test
6. No usar control de versiones correctamente
El error
Commits gigantes sin descripción: "fix", "changes", "final version 2".
Cómo evitarlo
Use commits atómicos con convención semántica:
# Formato: <tipo>(<alcance>): <descripción>
git commit -m "feat(auth): add email validation to login form
- Validate email format before submission
- Display inline error for invalid emails
- Add unit tests for validation logic
Closes #123"
# Tipos: feat, fix, docs, style, refactor, test, chore
7. Optimización prematura
El error
Intentar optimizar código antes de que sea necesario, sacrificando legibilidad.
// Sobre-optimización innecesaria
func processUsers(users []User) []ProcessedUser {
result := make([]ProcessedUser, 0, len(users))
// Usar bits para flags (confuso sin beneficio medido)
const (
FLAG_ACTIVE = 1 << 0
FLAG_VERIFIED = 1 << 1
)
// ... código complejo innecesario
}
Cómo evitarlo
Escriba código legible primero, optimice solo cuando haya datos que lo justifiquen.
// Versión clara y mantenible
func processUsers(users []User) []ProcessedUser {
result := make([]ProcessedUser, 0, len(users))
for _, user := range users {
result = append(result, ProcessedUser{
ID: user.ID,
Active: user.Active,
Verified: user.Verified,
})
}
return result
}
// Solo optimizar después de benchmark si es necesario
Regla de oro: "Make it work, make it right, make it fast" — en ese orden.
8. No leer la documentación oficial
El error
Depender exclusivamente de tutoriales o respuestas de IA sin verificar con fuentes oficiales.
Cómo evitarlo
Consulte la documentación oficial primero. Ejemplo después de leer los docs de requests:
import requests
from typing import Dict, Any
def fetch_api(url: str, timeout: int = 10) -> Dict[str, Any]:
"""Fetch data from API endpoint de forma segura."""
if not url.startswith(('http://', 'https://')):
raise ValueError(f"Invalid URL: {url}")
try:
response = requests.get(
url,
timeout=timeout,
verify=True, # Siempre verificar SSL
headers={'Accept': 'application/json'}
)
response.raise_for_status()
return response.json()
except requests.Timeout:
raise RequestException(f"Request timed out after {timeout}s")
except requests.RequestException as e:
raise RequestException(f"Request failed: {e}")
9. No hacer code reviews efectivos
El error
Aprobar PRs sin leer o escribir "LGTM 👍" sin comentarios útiles.
Cómo evitarlo
Como autor del PR:
## Pull Request: Implement User Authentication
### Cambios
- ✅ Add JWT token generation and validation
- ✅ Implement refresh token rotation
- ✅ Add rate limiting to login endpoint
### Testing
- Unit tests (coverage: 95%)
- Integration tests para login flow
### Checklist
- [x] Tests passing
- [x] Documentation updated
- [x] No console.logs
Closes #234
Como reviewer:
### Bloquea merge:
**Security:** `src/auth/login.js:45`
❌ Password se está loggeando — nunca loggear contraseñas
**Bug:** `src/api/users.js:123`
❌ Race condition — falta await en sendWelcomeEmail
### Sugerencias:
Considera usar bcrypt en lugar de SHA256 para passwords
### Positivo:
✅ Excelente manejo de errores
✅ Tests muy completos
10. Sobre-ingenierizar soluciones simples
El error
Aplicar patrones complejos a problemas que requieren soluciones directas.
// Complejidad innecesaria para app simple
interface IUserFactoryStrategy { }
class UserFactoryProvider { }
// ... 50 líneas más para crear un usuario
Cómo evitarlo
// Solución directa
class User {
public static User fromDTO(UserDTO dto) {
return new User(dto.getName(), dto.getEmail());
}
}
// Uso simple
User user = User.fromDTO(userDTO);
Principio: Comience simple. Agregue complejidad solo cuando los requerimientos lo demanden.
11. No pedir ayuda cuando están atascados
El error
Pasar horas luchando con un problema por miedo a parecer incompetente.
Cómo evitarlo
Regla de los 30 minutos: Si estás atascado por 30+ minutos sin progreso real, pide ayuda. Cómo hacerlo efectivamente:
## Problema
JWT token no se valida en middleware — recibo error 401 "Invalid token"
## Comportamiento esperado vs actual
- Esperado: Token válido permite acceso
- Actual: Token falla validación
## Lo que ya intenté
1. Verifiqué que el secret es igual en generación y validación ✅
2. Confirmé que el token se envía en el header correcto ✅
3. Probé con jwt.io — token es válido ✅
## Código relevante
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET);
const decoded = jwt.verify(token, process.env.JWT_SECRET); // Falla aquí
## Error exacto
JsonWebTokenError: invalid signature at verify.js:123
## Pregunta específica
¿Hay casos donde el secret podría diferir entre procesos?
Conclusión
La diferencia entre un junior que progresa rápidamente y uno que se estanca está en:
- Reconocer los errores cuando los cometes
- Entender por qué son problemáticos
- Aplicar las soluciones conscientemente
- Pedir feedback regularmente
En 2026, con IA generando código, el valor del desarrollador está en saber qué preguntar, cómo revisar críticamente y diseñar arquitecturas sólidas.
© Copyright: Natalia Jaimes
Comentarios
Publicar un comentario