﻿# LL-Dominus: Arquitectura y normas de desarrollo

Este documento es la referencia oficial para modificar LL-Dominus. Antes de tocar código, leer estas normas y respetar la arquitectura del proyecto.

## 1. Filosofía del proyecto

LL-Dominus está diseñado para durar muchos años. La arquitectura tiene prioridad sobre la rapidez de implementación.

El proyecto debe mantenerse limpio, mantenible, orientado a objetos y fácil de trasladar conceptualmente a Harbour/Xailer en el futuro.

El diseñador visual y el motor de ejecución son módulos independientes. Pueden compartir clases de objetos, pero no deben mezclar responsabilidades.

## 2. Arquitectura

La arquitectura general se compone de estas piezas:

- **Plantilla**: representa la definición del informe o etiqueta. Contiene tamaño de papel, configuración visual y objetos.
- **Conector de datos**: carga datos externos y los ofrece al motor sin conocer la plantilla.
- **Motor de ejecución**: coordina plantilla, datos, contexto, composición, paginación y renderizado.
- **Contexto de ejecución**: agrupa conector, evaluador, opciones y avisos controlados durante la ejecución.
- **Evaluador de fórmulas**: resuelve variables, fórmulas y condiciones sin usar `eval`.
- **Motor de composición**: convierte objetos de plantilla en objetos renderizables.
- **Motor de paginación**: organiza los objetos renderizables en páginas.
- **Documento renderizable**: estructura intermedia lista para ser enviada a un renderizador.
- **Renderizadores**: generan una salida concreta, por ejemplo HTML. PDF será un renderizador independiente cuando se implemente.

Cada clase debe tener una única responsabilidad. No crear clases gigantes ni mezclar diseño, datos, composición, paginación y renderizado en la misma clase.

## 3. Objetos

Los objetos del diseñador son también los objetos del motor. No deben existir clases duplicadas para diseño y ejecución.

El diseñador usa los objetos para editar, seleccionar y mostrar propiedades. El motor usa esos mismos objetos para generar objetos renderizables.

Ejemplos de objetos compartidos:

- `TObjectBase`
- `TText`
- `TRectangle`

Antes de crear un nuevo objeto, comprobar si puede heredar comportamiento común de `TObjectBase` o de una clase puente existente.

## 4. Ciclo de vida

Todas las clases principales deben seguir el mismo ciclo conceptual:

```text
new()
  ↓
init()
  ↓
create()
  ↓
end()
```

Esta filosofía es común a Harbour, PHP y JavaScript.

- `new()`: punto de entrada de creación cuando el lenguaje lo permite. Debe instanciar y delegar en `init()`.
- `init()`: inicialización ligera, valores por defecto y parámetros iniciales. No debe activar el objeto ni crear recursos pesados.
- `create()`: activa el objeto. Aquí se carga, crea DOM, enlazan eventos, se lee un fichero o se prepara realmente el objeto.
- `end()`: libera referencias, eventos, DOM, recursos o deja el objeto inactivo.

En JavaScript, `new` es operador del lenguaje. Por tanto, el patrón equivalente es:

```text
constructor()
  ↓
init()
  ↓
create()
  ↓
end()
```

El constructor JavaScript debe ser mínimo.

## 5. Convenciones de clases

Todas las clases propias del proyecto empiezan por `T`.

Ejemplos:

- `TDocument`
- `TObjectBase`
- `TText`
- `TRectangle`
- `TPlantilla`
- `TConectorDatos`
- `TMotorEjecucion`
- `TEvaluadorFormulas`
- `TRenderizadorHtml`

Una clase debe tener una responsabilidad clara. Si una clase empieza a coordinar demasiadas cosas, dividirla en gestores o clases específicas antes de seguir creciendo.

## 6. Orden interno de una clase

Todas las clases deben seguir este orden interno:

```text
Constantes
Propiedades privadas
Propiedades protegidas
Propiedades públicas
new()
init()
create()
end()
Métodos públicos
Métodos protegidos
Métodos privados
```

Si el lenguaje no soporta alguna sección, se omite. El bloque de ciclo de vida debe aparecer siempre al principio de los métodos.

## 7. Estilo de programación

Los métodos triviales de una sola instrucción deben escribirse en una línea.

Ejemplo:

```php
public function getNombre(): string { return $this->cNombre; }
```

```js
getName() { return this.cName; }
```

Los métodos con condiciones, bucles, composición de estructuras o lógica relevante deben escribirse en formato vertical.

Usar nombres descriptivos y prefijos Dominus:

- `n` para números.
- `c` para cadenas.
- `l` para lógicos.
- `d` para fechas.
- `t` para fecha/hora.
- `a` para arrays.
- `o` para objetos.
- `h` para hashes.
- `u` para valores genéricos.

Ejemplos:

- `nLeft`
- `nTop`
- `nWidth`
- `nHeight`
- `cName`
- `cId`
- `lVisible`
- `oParent`
- `aObjects`
- `hData`

Todas las coordenadas internas deben estar en milímetros. Los píxeles son solo representación visual.

## 8. PHP

Normas específicas para PHP:

- Todas las clases principales deben implementar `new()`, `init()` si procede, `create()` y `end()`.
- `new()` debe delegar en `init()`.
- `create()` debe devolver siempre el propio objeto (`$this`) salvo que exista una razón arquitectónica clara.
- `end()` debe existir aunque inicialmente no libere recursos.
- No usar `eval`.
- Ejecutar `php -l` en los PHP modificados antes de finalizar.
- Mantener UTF-8.
- No duplicar lógica de serialización: los objetos guardan y cargan sus propias propiedades.

## 9. JavaScript

Normas específicas para JavaScript:

- Las clases principales deben usar `constructor()`, `init()`, `create()` y `end()`.
- El constructor debe ser mínimo.
- `init()` configura valores iniciales.
- `create()` crea DOM, enlaza eventos o deja el objeto operativo.
- `end()` libera eventos, DOM y referencias.
- No mezclar lógica del diseñador con lógica del motor.
- Mantener métodos simples en una línea.
- Comprobar sintaxis con `node --check` cuando se modifiquen ficheros JavaScript.

## 10. Motor

El motor no debe modificar la plantilla original.

El motor trabaja con objetos ya creados, evalúa su visibilidad de ejecución y genera objetos renderizables.

Flujo conceptual:

```text
plantilla + datos
  ↓
contexto de ejecución
  ↓
objetos reales
  ↓
objetos renderizables
  ↓
renderizador
```

El motor debe respetar:

- orden de dibujo;
- visibilidad común;
- condiciones de aparición;
- propiedades visuales reales;
- coordenadas en milímetros.

## 11. Diseñador

El diseñador es una vista editable. Debe mostrar los objetos aunque tengan condición de aparición.

Regla de visibilidad:

```text
Diseñador normal:
  respeta lVisible
  no evalúa cCondition

Motor de ejecución:
  respeta lVisible
  sí evalúa cCondition
```

Las condiciones solo se evalúan durante la ejecución o en una vista previa real con contexto de datos.

El diseñador debe permitir:

- cargar plantilla;
- seleccionar objetos;
- editar propiedades;
- guardar plantilla;
- recargar plantilla;
- mantener visible y editable `cCondition`.

## 12. Pruebas

Antes de finalizar cualquier cambio, ejecutar las pruebas adecuadas al área modificada.

### PHP

- `php -l` sobre los ficheros PHP modificados.
- Probar `public/motor/index.php`.
- Probar `public/motor/index.php?debug=1`.

### JavaScript

- `node --check` sobre los ficheros JS modificados.
- Abrir diseñador.
- Cargar plantilla.
- Seleccionar `TText`.
- Seleccionar `TRectangle`.
- Comprobar panel de propiedades.
- Comprobar que `cCondition` se ve y se puede editar.
- Guardar plantilla.
- Recargar plantilla.
- Revisar consola del navegador sin errores.

### Harbour

- El Engine definitivo será Harbour. El Engine PHP actual es la referencia funcional durante la migración.
- No portar el Engine completo de una vez. Las traducciones se hacen clase por clase, después de analizar el PHP real, sus dependencias y sus pruebas o usos reales.
- No afirmar que una clase Harbour funciona si no se ha compilado. No afirmar equivalencia funcional con PHP si no se ha probado.
- Usar los BAT oficiales de `tools/harbour` para compilar, ejecutar y limpiar. Las reglas específicas están en `tools/harbour/AGENTS.md`.

## 13. Antes de crear código nuevo

Antes de crear una clase nueva, método nuevo o propiedad nueva, comprobar:

- si ya existe algo equivalente;
- si puede reutilizarse;
- si la funcionalidad encaja dentro de una clase existente;
- si pertenece al diseñador, al motor o a una clase compartida;
- si duplica una responsabilidad existente.

Evitar duplicar código, clases y responsabilidades.

No implementar parser LST/LBL, PDF, impresión o tablas salvo petición expresa.

## 14. Regla principal

> Antes de escribir una sola línea de código, pensar primero en la arquitectura.

En LL-Dominus, la arquitectura tiene prioridad sobre la implementación.
