630 lineas de framework, una tienda con subastas, y cero lineas picadas a mano
Hay un momento en el desarrollo de un framework en el que dejas de hablar de lo que puede hacer y empiezas a usarlo para hacer cosas. Ese momento llego.
El experimento
La pregunta era simple: puede alguien que no conozca Cohete montar
algo real con composer create-project cohete/skeleton? No un
Todo. No un CRUD. Algo con dominio, con eventos, con WebSocket, con
subastas en tiempo real.
La respuesta es si. Y lo hemos demostrado.
Lo que NO hicimos
No escribimos un router. No configuramos un DI container. No montamos un servidor HTTP. No integramos WebSocket. No implementamos un message bus. No creamos un sistema de middleware. No hicimos un ORM. No configuramos CORS. No montamos SSE para MCP.
Todo eso ya estaba. 630 lineas de framework + 120 de DDD library + un
skeleton que arranca con php src/bootstrap.php.
Lo que SI hicimos
Escribimos dominio. Solo dominio.
- Un
Harvestaggregate que sabe cuantos litros de aceite quedan y a que precio se venden - Un
PricingPolicydomain service que calcula el precio segun el stock (una funcion pura, sin estado, sin dependencias) - Un
Auctionaggregate con pujas, estados, y un ciclo de vida completo - Un
Orderaggregate que distingue entre compra directa y victoria de subasta - Value Objects:
Money(centimos + moneda),Liters(entero positivo),Email(validado),Address - Domain Events:
LitersSold,PriceTierChanged,BidPlaced,AuctionClosed,OrderPlaced
Todo esto extiende AggregateRoot de
cohete/ddd. Los eventos se publican por el
MessageBus del framework. Los repositories
implementan una interfaz async (PromiseInterface). Los controllers son una linea
de DI + una llamada al dominio.
La maravilla del control absoluto
Aqui esta lo que diferencia a Cohete de un framework grande.
En Laravel, montas un e-commerce con 15 paquetes de Composer, 3 capas de abstraccion, un ORM que te esconde las queries, y un event system que funciona por magia. Si algo falla, tienes 200 ficheros de vendor que no entiendes.
En Cohete, tienes TU dominio y un framework que cabe en un pantallaz.
Sabes exactamente que pasa en cada request porque no hay magia: un Kernel que resuelve la ruta con FastRoute, un
ContainerFactory que inyecta dependencias
con PHP-DI, y un ReactMessageBus que emite
eventos con EventEmitter.
Si algo falla, abres 630 lineas de PHP y lo lees. No necesitas Xdebug. No necesitas Stack Overflow. Lo lees.
Y lo mas importante: el framework no te obliga a
nada. No hay convenciones de nombres. No hay carpetas magicas.
No hay "artisan make:model". Creas un fichero PHP, implementas HttpRequestHandler, lo registras en routes.json, y funciona.
Lo que el skeleton te da gratis
Cuando haces composer create-project cohete/skeleton,
tienes:
| Feature | Estado | Activacion |
|---|---|---|
| HTTP server async | Funciona | Siempre |
| DI container con autowiring | Funciona | Siempre |
| Router (FastRoute) | Funciona | Siempre |
| Message Bus (in-memory) | Funciona | Siempre |
| Domain Events | Funciona | Siempre |
| AggregateRoot + Value Objects | Funciona | Siempre |
| Web Components frontend | Funciona | Siempre |
| Static file serving (con cache) | Funciona | Siempre |
| MySQL async | Opt-in | MYSQL_HOST env var |
| RabbitMQ | Opt-in | RABBITMQ_HOST env var |
| MCP stdio (IA local) | Funciona | php src/mcp-server.php |
| MCP SSE (IA remota) | Funciona | /mcp/sse endpoint |
Sin env vars, todo corre in-memory. Zero dependencias externas. Arranca en 1 segundo. Anadir MySQL es poner una variable de entorno. Anadir RabbitMQ es otra. El dominio no cambia.
WebSocket: el event loop es tu amigo
En la tienda de aceite, cuando alguien compra litros, TODOS los navegadores conectados ven el medidor de stock bajar en tiempo real. Esto no es Socket.IO, no es Pusher, no es un servicio externo.
Es el mismo proceso PHP. El mismo event loop. HTTP en el puerto 8080,
WebSocket en el 8081. Comparten memoria, comparten el message bus. Un
domain event LitersSold se publica, el
suscriptor WebSocket lo recoge y hace broadcast. Cero latencia, cero red
entre servicios.
Eso es lo que te da un servidor async single-process: todo esta en el mismo sitio. No necesitas Redis para pub/sub entre procesos. No necesitas un broker de mensajes para comunicar HTTP con WebSocket. Es UN proceso con UN event loop.
11 tests en 34 milisegundos
El dominio de la tienda tiene 11 unit tests que cubren:
- Creacion de cosecha (emite
HarvestCreated) - Venta de litros (reduce stock, emite
LitersSold) - Cruce de tier de precio (emite
PriceTierChanged) - Rechazo de venta cuando no hay stock suficiente
- Reconstruccion desde DB (sin emitir eventos)
- Pricing correcto segun porcentaje de stock
34 milisegundos. Sin base de datos. Sin mock framework. Solo PHP puro llamando a objetos de dominio.
El veredicto
630 lineas de framework. 120 de DDD. Una tienda con subastas en tiempo real, pricing dinamico, WebSocket, MCP, y dominio DDD limpio. Desplegada en produccion en un VPS de 7 euros al mes.
No hemos picado ni una linea de infraestructura HTTP. No hemos configurado un servidor. No hemos montado un ORM. Hemos escrito dominio, controllers, y Web Components. El framework se encarga del resto.
Eso es lo que un framework minimalista bien disenado te permite: control absoluto con esfuerzo minimo. No es magia. Son 630 lineas que puedes leer, entender, y modificar si hace falta.
—
composer create-project cohete/skeleton mi-proyecto && php src/bootstrap.php.
Lo demas es tu dominio.
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario