Full stack developer
Cómo escribo el software: pruebas primero y piezas que se pueden cambiar.
TDD, SOLID, integración continua y unas cuantas reglas más que no negocio. Aquí está cada una con su motivo, un caso donde se aplica y el texto público donde está definida.
- Pruebas TDD, pirámide de pruebas
- Diseño SOLID, hexagonal, KISS y YAGNI
- Entrega CI/CD, versionado semántico, doce factores
Las reglas que no negocio
No son manías: cada una se paga sola la primera vez que hay que cambiar algo con el programa ya funcionando y gente dentro.
Un encargo pequeño y uno grande se escriben igual. La diferencia está en cuántas veces vas a volver: el software que resuelve un proceso de una empresa se toca cada pocos meses porque el proceso cambia, y lo que decide si eso es barato o carísimo se decidió el primer día, cuando se eligió dónde poner cada frontera.
- Una prueba antes que el código Si no sé escribir la prueba, todavía no sé qué le estoy pidiendo al programa. Escribirla primero es la forma más corta de averiguarlo.
- Cada pieza, un solo motivo para cambiar Responsabilidad única y dependencias hacia dentro: el caso de uso no sabe si detrás hay PostgreSQL, un fichero o la API de un tercero.
- Lo aburrido gana Ninguna dependencia entra sin explicar qué problema resuelve hoy. Lo que no hace falta, no se escribe.
- El error se dice, no se esconde Una API contesta el fallo en un formato que la otra parte puede leer, con su código y su motivo, no con un 200 y un texto suelto.
- La entrega se repite igual Configuración fuera del código, despliegue repetible y versión numerada: el servidor de producción no es una pieza artesanal.
- La seguridad se revisa con lista Antes de dar algo por bueno, el repaso de siempre: autenticación, permisos, entrada del usuario, dependencias y registros.
Lo que no hago
Casi todo el trabajo de mantener algo barato consiste en lo que se decidió no meter.
No empiezo eligiendo framework. Primero está el proceso que hay que resolver y el dato que hay que guardar; la herramienta se elige después, y a veces la respuesta es que no hace falta ninguna. Esta misma web es el ejemplo: PHP plano, sin base de datos, sin dependencias y sin paso de compilación, porque nada de lo que hace lo pedía. Se puede leer entera y se sirve con un servidor web y nada más.
No escribo código «para cuando haga falta». Una capa de abstracción que todavía no tiene dos implementaciones no es flexibilidad: es una pieza más que mantener y una indirección más que leer. Cuando aparece la segunda, se extrae, y para entonces las pruebas ya están escritas y el cambio es mecánico.
Y no dejo la interfaz para el final. Lo que se ve tiene su propio método, sus propias reglas de contraste y de foco, y no se improvisa la tarde antes de entregar.
Glosario del oficio.
Los términos tal como se usan, con un caso donde aplico cada uno y el texto público que lo define. Así no hay que creerme: se puede comprobar.
- TDD · Desarrollo guiado por pruebas Escribir primero una prueba que falla, después el código mínimo que la hace pasar y solo entonces limpiar el resultado. Es el ciclo rojo-verde-refactor, y ordena el diseño antes de que haya código que defender. Ejemplo: En un validador de formulario, la primera prueba es la del correo inválido: hasta que no falla por el motivo correcto, no se escribe el validador. Cuando meses después hay que admitir un dominio nuevo, esa prueba sigue vigilando los otros casos. Fuente: Test-Driven Development, Martin Fowler
- Pirámide de pruebas · Testing pyramid Muchas pruebas unitarias rápidas abajo, unas cuantas de integración en medio y muy pocas de extremo a extremo arriba. Cuanto más arriba, más tarda y más frágil es, así que arriba solo va lo que de verdad hay que comprobar entero. Ejemplo: El cálculo de los días de vacaciones que le quedan a alguien se prueba decenas de veces en unitarias; la pantalla completa, con navegador, una sola vez. Fuente: Test Pyramid, Martin Fowler
- SOLID Cinco principios de diseño: responsabilidad única, abierto-cerrado, sustitución de Liskov, segregación de interfaces e inversión de dependencias. Todos apuntan a lo mismo: que un cambio previsible se haga en un sitio y no en catorce. Ejemplo: Añadir una forma de pago nueva debería ser una clase nueva y un renglón de configuración. Si hay que abrir el cálculo del pedido para meter un «si es la pasarela nueva, entonces…», el diseño está avisando. Fuente: SOLID Relevance, Robert C. Martin
- Arquitectura hexagonal · Puertos y adaptadores La lógica del negocio se queda en el centro y todo lo de fuera —base de datos, API, correo, pantalla— entra por un puerto con su adaptador. El centro no sabe quién le habla. Ejemplo: El envío del correo de un formulario va detrás de una interfaz: en producción sale por SMTP y en las pruebas se escribe en un fichero, sin tocar ni una línea de la lógica. Fuente: Hexagonal Architecture, Alistair Cockburn
- KISS, YAGNI y DRY · Simplicidad primero Tres atajos para lo mismo: hazlo simple, no lo construyas hasta que haga falta y no repitas la misma decisión en dos sitios. El orden importa, porque quitar repetición antes de tiempo también acopla. Ejemplo: Esta web: sin base de datos, sin dependencias y sin build. El contenido vive en tres ficheros y el sitio se sirve con un servidor web y nada más. Fuente: Yagni, Martin Fowler
- Refactorización Cambiar cómo está escrito el código sin cambiar lo que hace, en pasos pequeños y con las pruebas en verde todo el rato. No es «reescribirlo»: reescribir es empezar de cero y perder lo aprendido. Ejemplo: Una función de cuatrocientas líneas se parte en cinco con nombre propio, una a una, ejecutando las pruebas entre paso y paso. Si algo se rompe, se sabe exactamente en qué paso. Fuente: Refactoring, Martin Fowler
- CI/CD · Integración y entrega continuas Integrar el trabajo en la rama principal a menudo, con las pruebas pasando en cada integración, y tener siempre una versión lista para salir. Lo que se acumula durante semanas se rompe todo junto y el mismo día. Ejemplo: Cada cambio pasa la batería de pruebas antes de fusionarse; el despliegue es el mismo guion siempre, así que subir es rutina y no un acontecimiento. Fuente: Continuous Integration, Martin Fowler
- Versionado semántico · SemVer 2.0.0 Numerar las versiones como mayor.menor.parche, donde el primer número solo sube cuando se rompe la compatibilidad. El número deja de ser decorativo y pasa a ser una promesa. Ejemplo: Quien consume una API sabe que puede actualizar de 2.3.1 a 2.4.0 sin tocar su integración, y que un salto a 3.0.0 hay que leerlo antes. Fuente: Semantic Versioning 2.0.0
- Commits convencionales Escribir el motivo del cambio con un prefijo fijo —fix, feat, refactor…— para que el historial se pueda leer y de él salgan las notas de versión y el número siguiente. Ejemplo: El historial del proyecto contesta «¿por qué está esto así?» sin tener que preguntarle a nadie, que es justo lo que no puede hacer un comentario en el código. Fuente: Conventional Commits 1.0.0
- Doce factores · Twelve-Factor App Doce reglas para que una aplicación se pueda desplegar, escalar y mover sin sorpresas: configuración en el entorno, dependencias declaradas, procesos sin estado, registros como flujo. Ejemplo: Las credenciales no viven en el repositorio, sino en el fichero de configuración del servidor, fuera del directorio que se publica. La misma aplicación arranca en local y en producción cambiando solo ese fichero. Fuente: The Twelve-Factor App
- Problem Details · RFC 9457 Un formato estándar para contar el error de una API: tipo, título, estado, detalle e instancia. Sirve para que quien la consume programe el caso malo en vez de adivinarlo leyendo cadenas de texto. Ejemplo: Una integración con un ERP distingue «el documento no existe» de «no tienes permiso» por el campo del error, y no por si el mensaje trae la palabra «permiso». Fuente: RFC 9457, Problem Details for HTTP APIs (IETF)
- OWASP Top 10 La lista de los diez riesgos de seguridad más habituales en aplicaciones web, mantenida por la fundación OWASP. Funciona como lista de repaso: la mayoría de los agujeros reales están ahí. Ejemplo: Antes de publicar, el repaso de siempre: control de acceso por recurso y no por pantalla, consultas con parámetros, dependencias al día y registros que no escupen datos personales. Fuente: OWASP Top 10
- Calidad de producto · ISO/IEC 25010 El modelo internacional que descompone la calidad de un producto de software en nueve características —entre ellas mantenibilidad, seguridad y fiabilidad— con sus subcaracterísticas. Sirve para discutir calidad con palabras concretas. Ejemplo: Cuando alguien pide «que sea robusto», el modelo obliga a separar qué parte es fiabilidad, qué parte es seguridad y qué parte es simplemente que la pantalla se entienda. Fuente: ISO/IEC 25010:2023
Preguntas.
¿Escribir las pruebas primero no va más lento?
El primer día, sí. El cálculo cambia en cuanto hay que tocar algo que ya está en producción: sin pruebas, cada cambio obliga a repasar a mano lo que antes funcionaba, y eso se paga cada vez. Con pruebas se paga una.
¿Se puede aplicar SOLID sin framework, en PHP plano?
SOLID no es una biblioteca, es dónde se ponen las fronteras. Se puede hacer mal con el framework más moderno y bien con un puñado de ficheros: lo que importa es que la lógica no sepa de dónde viene el dato ni a qué pantalla va.
¿Qué cobertura de pruebas buscas?
No persigo un porcentaje. Un número alto con pruebas que no comprueban nada da falsa tranquilidad. Lo que busco es que lo que duele si se rompe —el cálculo, el permiso, el dinero— esté cubierto, y que un fallo en producción deje siempre una prueba nueva detrás.
¿Y si el proyecto ya existe y no tiene nada de esto?
Se empieza por donde se va a tocar. Antes de cambiar una pieza, se le escriben pruebas que fijen lo que hace hoy —aunque lo que haga hoy sea raro—; con esa red, el cambio deja de ser una apuesta. Reescribir entero casi nunca es la respuesta.
¿Quién decide cuándo algo está terminado?
Lo decide una lista escrita antes de empezar, no la sensación de que ya va: las pruebas pasan, el error está contado en su formato, la pantalla se puede usar con teclado y con lector, la versión está numerada y el despliegue se ha hecho con el mismo guion de siempre.
Fuentes.
Todo lo que se afirma aquí está descrito en un texto público. Estos son, con su organismo y su fecha.
- ISO/IEC 25010:2023 · Modelo de calidad de producto ISO/IEC JTC 1/SC 7 · 2023-11
- RFC 9110 · HTTP Semantics IETF · 2022-06
- RFC 9457 · Problem Details for HTTP APIs IETF · 2023-07
- OWASP Top 10 OWASP Foundation · 2021
- OWASP Application Security Verification Standard OWASP Foundation
- Semantic Versioning 2.0.0 semver.org
- The Twelve-Factor App Heroku
- Conventional Commits 1.0.0 Conventional Commits
- Continuous Integration Martin Fowler
- Hexagonal Architecture Alistair Cockburn
- DORA · investigación sobre entrega de software DORA (Google Cloud)
Adónde seguir.
- El stack, herramienta por herramienta Qué hace cada lenguaje, cada base de datos y cada pieza de sistemas, y con qué criterio se elige.
- Las aplicaciones que he construido Dónde se ve todo esto funcionando, con enlace para probarlo.
- Y el método del otro lado Interfaz, accesibilidad y sistema de marca: las reglas de lo que se ve.
¿Hablamos?
¿Te cuadra esta forma de trabajar?
Cuéntame qué tienes entre manos y te digo por dónde empezaría.

