Premisas de Arquitectura

Premisas de Arquitectura

Fundamentos técnicos para sistemas PHP medianos a complejos

Introducción

Después de 33 años desarrollando en sistemas y unos 18 de PHP, he consolidado un conjunto de premisas arquitectónicas que han demostrado su eficacia en proyectos reales no solo de PHP pero lo pongo como ejemplo. Estas premisas priorizan la operabilidad real sobre la elegancia teórica, enfocándose en sistemas que funcionan, se mantienen y evolucionan exitosamente a lo largo del tiempo.

Los sistemas que desarrollo típicamente manejan 30-80 usuarios con 20 concurrentes, representando el espectro mediano-complejo donde estas decisiones arquitectónicas tienen mayor impacto.

Premisa 1: Monolito (catedral) vs. Bazar

Contrario a las tendencias actuales que favorecen arquitecturas distribuidas, elijo deliberadamente por enfoques monolíticos estructurados por las siguientes razones fundamentales:

Costo de Mantenimiento

Un sistema con código disperso en cientos o miles de archivos convierte cualquier cambio en una pesadilla. Hacer modificaciones requiere buscar en múltiples ubicaciones, sin garantía de entender el impacto completo. En contraste, concentrar la funcionalidad en 5-15 archivos centrales permite:

  • Localización inmediata de cualquier funcionalidad
  • Comprensión completa del flujo de ejecución
  • Cambios controlados con impacto predecible

Respaldos Quirúrgicos

Cuando ocurre una regresión, la arquitectura monolítica permite identificar exactamente qué archivo cambió y restaurar únicamente ese componente desde respaldo. Esto es infinitamente superior a restaurar sistemas completos o buscar problemas en arquitecturas distribuidas.

Independencia de Red

No queremos depender de que múltiples servicios externos funcionen correctamente. Un servidor funcionando bien (más réplicas si es necesario) es más confiable que una orquestación compleja de microservicios.

Premisa 2: Programación Funcional/Estructurada vs. OOP

Aunque la Programación Orientada a Objetos tiene ventajas teóricas, en la práctica presenta problemas significativos que justifican un enfoque más directo.

El Problema de los Estados Cambiantes

Consideremos el ejemplo clásico de una puerta. Un programador inexperto modelará dos estados: abierta y cerrada. Uno más experimentado agregará «entreabierta». Pero la realidad incluye cinco estados:

  • CERRADA
  • CERRANDOSE
  • ENTREABIERTA
  • ABRIENDOSE
  • ABIERTA

Cuando descubres que necesitas nuevos estados de transición, todo el modelo de objetos se va al demonio. Hay que modificar clases base, actualizar herencias, revisar polimorfismo y probar que nada se rompió.

Doble Obsolescencia

Los lenguajes evolucionan, pero los frameworks lo hacen más agresivamente. mpdf para PHP 6-7 vs PHP 8 son bestias completamente diferentes. Con POO pesada, tu código depende de abstracciones externas que cambian constantemente, generando deuda técnica acumulativa.

Premisa 3: Centralización de Rutinas

Es común ver sistemas donde un PHP llama a otro PHP para procesos de 20 líneas, obligando a abrir 5-6 archivos diferentes para depurar funcionalidad simple.

Arquitectura de Router Central

Prefiero que cualquier proceso llame a un procedimiento capturado en router.php y contenido en archivos centrales . Por ejemplo, si el proyecto se llama FOUR, como unicoproyectoFOUR.php. La nomenclatura es autoexplicativa y todo el flujo es visible en 1-2 archivos.

  • index.php?module=altaproductos → Paso inicial
  • index.php?module=altaproductos&step=2 → Validación / guardar
  • index.php?module=altaproductos&step=3 → Confirmación o una tercera necesidad
  • index.php?module=altaproductos&step=n → Según evolución

Flujo por Steps

Este patrón, que uso desde 1995, permite:

  • Router simple sin sobrecarga
  • Flujo autoexplicativo
  • Escalabilidad trivial (agregar steps)
  • Debugging por componentes
  • Evolución sin romper funcionalidad existente

Premisa 4: Autosuficiencia Total

Los sistemas deben funcionar sin dependencias externas ni conectividad a internet.

Sin Composer ni Git Obligatorio

Muchos servidores de producción no tienen internet por razones de seguridad. Un sistema que requiere Composer o conexiones externas es arquitectónicamente frágil.

Control de Versiones por Fechas

sistema_20250620.zip es más claro y portable que commit hashes. Funciona offline y no requiere herramientas adicionales.

Seguridad Operativa

Sin Git obligatorio, un programador no puede clonar el sistema completo desde casa. Solo quien tiene acceso controlado al servidor de pruebas o producción puede trabajar con el código, reduciendo significativamente riesgos de seguridad.

Las dos únicas fugas que he visto en mi entorno directo son de factor humano, y de la era pregit pero perfectamente podrían pasar hoy fueron:

  • en 1997 porque le dieron el código fuente de mi sistema a alguien que yo había corrido de soporte en planta por cambiar claves de red novell sin avisar y recontrataron como mi QA  (configurando sabotaje industrial también despues pero la gracia costó unos 12 millones)
  • En 1999 en la misma empresa me hicieron quitar un código VB probado para que entrara un nuevo equipo y ellos  me preguntaban cosas tan simples como para que sirve la orden left. Finalmente dos años después entregaron una basura, se negaron a dar el código y nadie lo tenía respaldado. No se perdió mucho porque hacía 10% del mio, pero hubo que amenazar de cárcel al programador jefe para que lo regresara.

Así que además debe haber alguien que pruebe que los respaldos son reales.

Patrón común en los dos casos:

  • Señales de alerta temprana ignoradas (claves de red cambiadas sin autorización / pregunta sobre left)
  • Decisiones organizacionales que ignoran expertise técnico
  • Pérdidas millonarias por incompetencia humana, no fallas tecnológicas

Lo que hace valiosos estos ejemplos:

  1. Demuestran que la tecnología no es el problema – Las mejores herramientas no protegen contra mala gestión humana
  2. Validación de arquitectura de control – Las premisas están diseñadas específicamente para mitigar factor humano, no solo problemas técnicos (y en otro caso fuera del entorno de diseño, un jefe de sistemas ordenó formatear la única computadora con Código después de la salida del programador, por estar enojado y «procedimiento estandard» y se dieron cuenta meses despues que también habían formateado el disco duro de respaldo externo)
  3. 25 años de distancia – Suficiente tiempo para analizar objetivamente sin emociones del momento
  4. Casos reales con impacto medible – No son teorías, son pérdidas reales documentadas

La premisa «Sin Git obligatorio» cobra más sentido:

  • No es anti-tecnología
  • Es pro-control humano
  • Reconoce que las fugas de código son 99% factor humano, 1% falla técnica

Estos ejemplos refuerzan que la arquitectura está diseñada para equipos pequeños con control humano estricto, no para «democracia de código» donde cualquiera puede acceder a todo.

Son casos de estudio perfectos para justificar por qué priorizar control operativo sobre elegancia técnica.

Patrón actualizado:

  • Caso 1: Malicia + acceso indebido
  • Caso 2: Incompetencia técnica + retención hostil
  • Caso 3: Incompetencia administrativa + emociones

El punto se refuerza brutalmente: No importa qué herramientas uses (Git, backups automáticos, etc.), el factor humano puede destruir todo si no hay controles arquitectónicos estrictos.

El tercer caso es especialmente valioso porque muestra que incluso la «autoridad técnica oficial» (jefe de sistemas) puede ser el mayor riesgo si no hay arquitectura defensiva.

La lección: Los respaldos no sirven si están bajo el mismo control humano deficiente que el código principal.

El frontend y backend requieren arquitecturas completamente diferentes. Mezclar la interfaz gráfica con la lógica de negocio complica enormemente los cambios de diseño.

Pipeline de Presentación Unificado

El 95% de cualquier resultado del sistema aparece a través de un proceso único de presentación. Cada función de backend procesa su lógica y termina con:

return frontend($cadena);

Esto significa que funciones como altausuarios()editarproducto(), etc., hacen el proceso pero no se encargan de la presentación final. Solo generan contenido estructurado que la función frontend() convierte en HTML/php.

Ventajas de la Separación

  • Cambios independientes: Reestructurar UI sin tocar lógica de negocio
  • Trabajo en paralelo: Frontend y backend pueden desarrollarse simultáneamente por personas diferentes
  • Flexibilidad total: Cambiar metodologías de presentación sin impacto en el core
  • Consistencia visual: Toda la salida pasa por el mismo pipeline

Excepciones Justificadas

Existen casos especiales que no pasan por frontend():y se manejan en index o archivo extra

  • Descarga de archivos
  • Pantallas muy largas o especializadas
  • Respuestas AJAX específicas

Pero el principio central permanece: el proceso de negocio no debe preocuparse por la presentación final.

Premisa 6: Arquitectura de 5 Archivos Nucleares

En lugar de decenas de archivos dispersos, concentramos toda la funcionalidad en una arquitectura estándar de 5 archivos nucleares reutilizable entre proyectos. Aqui uso la palabra FOUR como las siglas del proyecto.

Los 5 Archivos Nucleares

1. index.php – Autoloader y Autenticación

  • Punto de entrada único del sistema
  • Carga librerías necesarias
  • Maneja login/logout como funciones internas (no archivos separados)
  • Hace require_once de frontend y router y lógica de negocio
  • Orquestación general del sistema

2. router.php – Despachador de Módulos

  • Interpreta parámetro ?module=
  • Decide qué función llamar según el módulo solicitado
  • Sin lógica de negocio, solo direccionamiento
  • Solo verifica el module e ignora los steps para flujos multi-paso, esos se manejan dentro de la función que evalua el parámetro en unicoFOUR.php

3. frontend.php – Pipeline de Presentación

  • Recibe contenido estructurado
  • Lo convierte en HTML final
  • Maneja layout, CSS, estructura visual
  • Consistencia de presentación en todo el sistema

4. unicoFOUR.php – Reglas de Negocio

  • Contiene todas las funciones específicas del proyecto
  • Lógica de negocio concentrada
  • Nomenclatura autoexplicativa del proyecto
  • Fácil localización de cualquier funcionalidad
  • Maneja las validaciones de permisos en cada proceso, y reacciona según el step en que esté en esa función (generalmente step=»» es presenta y step=2 guarda con un checkbox de confirmación) .

5. configFOUR.php – cosas unicas, ejemplo base de datos-

  • Mucho mas fácil de cambiar credenciales
  • otros parámetros como rutas de archivos, configuraciones de email, o límites de sistema
  • Hay que considerar que procesos específicos pueden necesitar mas memoria y se hace en ellos explicando porqué. Esta es la configuración estándar .

Ventajas de la Arquitectura Nuclear

En lugar de: login.php, logout.php, altausuarios.php, editarproducto.php… Tienes: 5 archivos nucleares + módulos específicos
  • Reutilización total: Login/logout son funciones, no archivos
  • Mantenimiento concentrado: Cambios en pocos puntos críticos
  • Arquitectura replicable: Mismo patrón proyecto a proyecto
  • Escalabilidad controlada: Agregar funcionalidad en ubicaciones predecibles

Nota: Pueden existir otros archivos PHP auxiliares (librerías, pruebas, herramientas), pero estos 5 constituyen el core estándar que se replica en cada proyecto.

Notas Aclaratorias

Sobre el Flujo por Steps (Premisa 3)

Los steps no requieren secuencia obligatoria. Cada step valida sus propios requisitos mediante condicionales como if (step()==2) que ejecuta solo si se cumplen las condiciones específicas. Si un usuario accede a un step inválido (ejemplo: step=3 sin cumplir requisitos), se maneja como cualquier proceso estándar generando un mensaje de error indicando que la entrada no es correcta. La numeración de steps es por claridad descriptiva, no secuencial. En el 99% de los casos solo existen step=»» (mostrar formulario) y step=2 (guardar datos), raramente se requiere step=3 ya que normalmente se procede con una llamada a otro proceso.

Sobre la Interacción de Archivos Nucleares (Premisa 6)

El flujo es específico: index.php siempre hace require_once de TODOS los archivos necesarios (router, frontend, unicoFOUR). frontend.php se invoca de dos maneras: 1) Por router cuando hay module definido: if ($module=='altausuarios') return frontend(altausuarios()), y 2) Por defecto desde index.php cuando no se ha definido module (página principal). router.php ignora los steps porque cada función en unicoFOUR.php maneja internamente sus propios steps según la lógica específica del proceso.

Sobre el Manejo de Errores y Excepciones

Errores de validación: Cada proceso maneja sus propias reglas de negocio (ejemplo: if edad<18 no puede comprar alcohol), incluyendo validación de campos obligatorios y prevención de inyección SQL. Fallos de base de datos: Después de secuencias de Insert/Update se verifica el éxito, si falla se ejecuta rollback y se muestra mensaje de error. Campo random: En entornos multiusuario, se inserta un valor aleatorio para identificar el registro específico del proceso actual, evitando validar el registro incorrecto cuando múltiples usuarios trabajan simultáneamente. Estados inconsistentes: Aunque no deberían suceder, todo error detectado se añade a la lógica del proceso. El administrador tiene acceso a un proceso llamado «barrido» que verifica estos errores para prevenir repetición (ejemplo: ¿por qué se vendió cerveza a un menor de 18 años?). Rollback de transacciones: Depende del contexto específico, en redes con mala señal se recomienda además usar principios ACID.

Sobre la Escalabilidad Vertical

Incluso en sistemas críticos bien diseñados, un archivo de 200KB no presenta problemas de rendimiento. El límite de 5000 líneas es por limitaciones de editores de texto, no por rendimiento. Cuando se alcanza este límite, los procesos obsoletos se mueven a archivos legacy, y los procesos críticos estables pueden tener su propio archivo (ejemplo: unicoFOUR2024 para rutinas que ya no se usan). En la práctica, un sistema de gestión con 2-3 programadores rara vez supera las 20,000 líneas únicas con este enfoque. Muchos procesos especializados que no requieren cambios mantienen su propio archivo. La arquitectura está pensada para equipos relativamente pequeños (típicamente 1 frontend + 1 backend). Ofrece escalabilidad limitada pero mucho mayor control. Un proyecto que reporte 715,000 LOC puede tener solo 60,000-120,000 líneas del sistema real sin dependencias externas.

Dudas específicas

  • Sobre la escalabilidad: Mencionas que rara vez se superan las 20,000 líneas, pero ¿qué sucede cuando un cliente crece inesperadamente? ¿Has tenido casos donde tuviste que migrar a una arquitectura más distribuida?
    • Escalabilidad vertical pragmática La solución de simplemente migrar a un VPS más potente o crecer el vultr es exactamente lo correcto para este contexto. Es mucho más eficiente y económico que reescribir toda la arquitectura. En México, donde muchas empresas buscan soluciones costo-efectivas, esto tiene perfecto sentido.
  • Testing: No veo mención explícita de estrategias de pruebas. Con funciones concentradas en unicoFOUR.php, ¿cómo manejas el testing unitario o de integración?
    • Un archivo de inyección por POST contra base separada es una estrategia muy práctica. Es testing funcional directo sin la sobrecarga de frameworks de testing complejos. Para equipos pequeños y sistemas monolíticos, esto es mucho más manejable y simple de mantener que Jest, PHPUnit y toda esa parafernalia.
  • Colaboración: Para equipos de más de 2-3 desarrolladores, ¿no se vuelve problemático que todos trabajen en el mismo archivo nuclear?
    • No. Fuera de De las empresas no trasnacionales o gigantescas como Walmart, las empresas en las que he estado por lo general solo tienen tres o cuatro programadores, y cada uno es responsable. En realidad el entorno en México va a una mezcla de devops + dba + prorgramador, y en su caso cada quien trabajan en cosas del directorio sandbox. El concepto del directorio sandbox para colaboración es inteligente – cada quien en su espacio sin conflictos.

Naturaleza del Documento

Este documento constituye una guía basada en experiencia práctica desarrollada desde 1995, aplicada exitosamente a través de múltiples empresas, diferentes bases de datos y varios lenguajes de programación. Las premisas han sido battle-tested durante tres décadas y representan soluciones probadas para contextos específicos, no dogmas universales.

Las mejores prácticas dicen …..

La principal objeción es: ¿por qué no usas la tecnología de moda (Microservices/Amazon/etc.)?

Lo simple tiene valor de supervivencia.

En resumen: No vas a matar moscas a cañonazos, especialmente considerando la economía en México.

Para el mercado mexicano y empresas medianas/pequeñas, una papelería con 20 sucursales o una fábrica de galletas con 500 empleados y 30 sucursales no necesita la complejidad (ni puede costear) una arquitectura de microservicios que puede costar entre $1,000 y $8,000 USD mensuales. Para ellos, un sistema sólido, mantenible y que funcione sin internet constante es mucho más valioso.

También podemos estimar más fácilmente el costo fijo, que en Amazon/AWS/Google Cloud no existe – el riesgo variable es brutal. Esta es una de las consideraciones de las premisas de arquitectura de software, pero el hardware de cada caso es diferente.

Esta arquitectura está diseñada para la realidad operativa de estas empresas:

  • Redes inestables
  • Presupuestos limitados
  • Equipos de desarrollo pequeños
  • Necesidad de control total del sistema
  • Mantenimiento simple

Si necesitas algo para decenas de programadores, tu producto final debe tener cientos de usuarios. Pero en la práctica, si tienes hasta 100-200 usuarios puedes escalar sin mucho problema con alta velocidad, más RAM y gastando poco. Un buen servidor dedicado o hardware escalable de costo fijo como Vultr o Diigital Ocean te dan costo manejable y valor de supervivencia. Si tienes respaldos, claro.

Conclusión

Estas 6 premisas han sido battle-tested durante 30 años, sobreviviendo a múltiples cambios de PHP, frameworks y modas arquitectónicas. Priorizan la realidad operativa sobre la elegancia teórica, resultando en sistemas que realmente funcionan, se mantienen eficientemente y evolucionan de manera predecible.

La arquitectura completa ofrece:

  • Backend monolítico estructurado
  • Programación funcional/procedimental
  • Centralización de rutinas con flujo por steps
  • Autosuficiencia total sin dependencias externas
  • Separación limpia de presentación
  • 5 archivos nucleares reutilizables

Para sistemas PHP de escala mediana (30-80 usuarios, 20 concurrentes), esta arquitectura ofrece el balance óptimo entre funcionalidad, mantenibilidad y control total del sistema.

Notas de Monolito cuatro

Voy a tener que reescribir algunos  proyectos juntando dos enfoques. Uno es el de monolitos que sería el equivalente de la Catedral y el Bazaar (modelos de implementación de software) para poder después integrarlo en un esquema Moprosoft de Documentación de una norma oficial mexicana que uso porque me quita muchos de los problemas de  CMMI

De momento me voy a concentrar en arquitectura.

Cosas por hacer:

Para Gestión de Negocio:

  • Justificación del proyecto y objetivos estratégicos
  • Análisis de viabilidad técnica y económica
  • Definición del alcance y beneficios esperados

Para Gestión de Proyectos:

  • Estimación de recursos y cronograma
  • Identificación de riesgos
  • Plan de calidad y métricas

Para Desarrollo:

  • Arquitectura técnica justificada
  • Especificaciones funcionales
  • Plan de pruebas y despliegue