Construir software desde primeros principios
Por qué empezamos por el problema y no por el stack, lo que cuesta y por qué compensa en el software que construimos — el nuestro y el de nuestros clientes.
La mayor parte del software actual se ensambla en lugar de diseñarse. Se elige un framework antes de que nadie haya escrito para qué sirve el sistema. Se clona una plantilla, se instalan una docena de paquetes “porque todo el mundo los usa”, y el problema real se dobla hasta que encaja con la forma de las herramientas.
Funciona. Durante un tiempo funciona muy bien — la primera demo llega en días, no en semanas. El problema aparece más tarde, en silencio, en el coste de cada cambio después del primero.
Esta nota va del otro camino, el que usamos tanto en nuestros productos como en el software a medida que desarrollamos para clientes: empezar por el problema, no por el stack.
Qué significa realmente “primeros principios”
La expresión se usa a la ligera, así que esto es lo que queremos decir en la práctica. Razonar desde primeros principios es descomponer un problema hasta las cosas que sabes que son ciertas — las restricciones que no se negocian — y construir desde ahí, en lugar de razonar por analogía (“la empresa X usa este stack, así que nosotros también”).
En software, la analogía es lo habitual. No es un mal instinto: las decisiones de otros contienen mucha experiencia ganada a pulso. Pero también contienen sus restricciones, el tamaño de su equipo, su tráfico, su historia. Copiar la solución sin las restricciones significa heredar una complejidad que nunca necesitaste.
Empezar por la restricción, no por la herramienta
Antes de escribir una línea de código intentamos responder tres preguntas, por escrito y con la mayor claridad posible:
- ¿Qué tiene que ser cierto para que esto funcione? No funcionalidades — invariantes. “Una factura nunca se emite dos veces.” “Un usuario solo ve sus propios datos.” “El informe tiene que estar listo a las 7:00 cada mañana.”
- ¿Qué es caro — en tiempo, dinero o atención — y por qué? A veces es la computación. Más a menudo son las personas: las horas cuadrando hojas de cálculo, los cambios de contexto, las comprobaciones manuales en las que ya nadie confía.
- ¿Qué podemos quitar sin perder nada que importe? Cada funcionalidad, pantalla e integración se examina para ver si sirve a alguna de las respuestas anteriores.
Las respuestas casi siempre apuntan a un sistema más pequeño y más preciso que el que habríamos construido por defecto. Solo entonces elegimos herramientas — y las elegimos para que encajen con las restricciones, no al revés.
Cada dependencia es una promesa
Un proyecto moderno puede arrastrar cientos de paquetes antes de hacer nada útil. Cada uno es una promesa que otra persona tiene que cumplir: que seguirá mantenido, seguro, compatible con todo lo demás, y que seguirá comportándose como hoy.
Fig. 1 — El mismo problema, dos grafos de dependencias. Cada línea de la izquierda es algo que puede romperse, cambiar de licencia o necesitar un parche.
No somos dogmáticos con esto. Usamos buenas librerías constantemente — escribir tu propia criptografía o tu propio driver de base de datos es un error. La regla es más sencilla: una dependencia tiene que ganarse su sitio. Si ahorra más de lo que cuesta durante la vida del sistema, se queda. Si está ahí porque la puso una plantilla, se va.
En la práctica, esto significa:
- Menos capas. Cada abstracción es un sitio donde se esconden bugs y donde las personas nuevas se pierden. Tres capas bien entendidas valen más que catorce finas.
- Decisiones aburridas donde no importa. Una base de datos relacional, HTTP sin adornos, páginas renderizadas en servidor cuando bastan. La novedad se reserva para donde el problema de verdad la exige.
- Fronteras explícitas. La lógica central del sistema no sabe qué framework la está pintando. Eso la hace testeable hoy y sustituible mañana.
La curva de costes que nadie planifica
El argumento real para construir así no es la elegancia. Es el coste — en concreto, el coste del siguiente cambio.
Fig. 2 — Ilustrativo. Un sistema diseñado suele costar algo más al principio, y mucho menos cada mes después.
Los sistemas ensamblados son baratos al principio porque la mayor parte del trabajo es prestado. Pero cada decisión prestada viene con supuestos, y a medida que el producto crece esos supuestos empiezan a chocar con la realidad. Cambios que deberían llevar una tarde llevan una semana. Las actualizaciones se posponen porque nadie sabe qué van a romper. Y al final alguien propone reescribirlo todo.
Un sistema diseñado a partir de sus restricciones suele tardar un poco más en llegar a la primera demo. Después, la curva se aplana: las nuevas funcionalidades encajan en una estructura pensada para recibirlas, y las personas que lo mantienen todavía pueden tenerlo entero en la cabeza.
Los sistemas pequeños envejecen bien
Hay un beneficio más discreto, y es el que más nos importa. El software construido así es legible. Una ingeniera nueva — tuya o nuestra — puede leerlo, entender por qué tiene la forma que tiene y cambiarlo con confianza. Eso importa mucho más que cualquier tecnología concreta, porque quienes mantienen un sistema dentro de tres años rara vez son quienes lo escribieron.
También es como entendemos la entrega en los proyectos para clientes. El objetivo no es que dependas de nosotros. Es dejarte algo lo bastante pequeño para entenderlo, lo bastante documentado para confiar en ello y lo bastante sólido para que rara vez necesites llamarnos.
Cómo se nota en nuestro trabajo
Cuando empezamos un proyecto a medida, el primer entregable no es código. Es un documento breve: los invariantes, las partes caras, lo que proponemos dejar fuera y la arquitectura que se deriva de todo eso. Suele ocupar unas pocas páginas, y es lo más valioso que producimos, porque cada decisión posterior se puede contrastar con él.
Después construimos — en incrementos pequeños y funcionales, cada uno desplegado y utilizable, para que veas cómo toma forma el sistema en lugar de esperar a una gran revelación final.
Si tienes un problema que las herramientas estándar casi resuelven, pero nunca del todo, cuéntanoslo. Empezar por el problema es lo que hacemos.