# Análisis Técnico Avanzado: SecInterp v3.11.0 La versión 3.11.0 consolida la madurez arquitectónica de SecInterp: el núcleo ya no depende de QGIS, los módulos monolíticos se han descompuesto y la interfaz se ha reorganizado alrededor de flujos de trabajo claros. Este análisis describe el estado técnico actual, sus métricas y la deuda que queda. **Versión**: 3.11.0 · **QGIS**: 3.28–4.99 · **Fecha**: 2026-10-24 --- ## 🏛️ Innovaciones Arquitectónicas ### 1. `core/` realmente QGIS-agnóstico El cambio más profundo de esta etapa: **`core/` ya no importa `qgis.*` ni `qgis.PyQt`**. La puerta `tests/core/test_architecture_boundary.py` mantiene una allowlist que ahora está **vacía**: ```python CORE_VIOLATIONS = {} ``` Las dependencias que antes estaban dispersas se sustituyeron por puertos y adaptadores: | Antes | Ahora | |---|---| | `QCoreApplication.translate` en core | `TranslatableMixin.set_translator(...)`; el plugin instala Qt | | `QgsSettings()` en `ConfigService` / `AccessControlService` | `SettingsStore`; `QgsSettingsStore` vive en `gui/adapters` | | `QgsVectorFileWriter` dentro de `core` | `exporters/qgis_io.py` | | `QgsMapSettings` en `core/services/export/` | `exporters/map_settings.py`; factory inyectada en `ExportService` | La composición raíz (`SecInterp`) crea el store de QGIS, el servicio de configuración y el control de acceso; `core` usa por defecto un `InMemorySettingsStore`. El resultado se puede comprobar sin QGIS: ```text CORE IMPORT OK ProfileController ExportService ``` > [!TIP] > **Impacto**: `core` es ahora testeable en Python puro y la frontera Core/GUI deja > de ser una convención para convertirse en una regla ejecutable. ### 2. Descomposición de módulos grandes La puerta de tamaño (`module_size_gate`, límite 400 líneas) está en **PASS** con **0 módulos >400**. | Módulo | Antes | Ahora | Estrategia | |---|---:|---:|---| | `core/controller.py` | 465 | **298** | fachada + procesadores de perfil | | `gui/adapters/geometry.py` | 598 | **69** | fachada + `geometry_*` | | `gui/preview_layer_factory.py` | 535 | **202** | fachada + `preview_layers/` | | `exporters/interpretation_3d_exporter.py` | 472 | **155** | fachada + `interpretation_3d/` | | `gui/preview_renderer.py` | 438 | **335** | collectors + cleanup | Los módulos extraídos conservan los puntos de parcheo de los tests mediante wrappers finos; la lógica de negocio se movió a piezas con una única responsabilidad. ### 3. Selección de sección y configuración de interpretaciones Dos mejoras de flujo completan la arquitectura de UI: - **Section Feature Selector** (`section_feature_selector.py`): lista **solo líneas de exactamente dos vértices**, con formato `fid — label` y campo de etiqueta `Auto` o un atributo. `section_feature_id` se propaga a topografía, geología, estructuras, sondajes, LOD y tareas asíncronas; las claves de caché ya lo aíslan. - **Interpretation Settings** es ahora una tab dentro de `SettingsPage`; el sidebar pasó de 7 a **6 entradas**. `MainWindow.page_interpretation` sigue siendo un alias del tab, por lo que persistencia y consumidores no cambiaron. --- ## 🚀 Extract-then-Compute y puertos El patrón de dos etapas sigue siendo el eje del diseño: 1. **Extracción (GUI, hilo principal)**: los adapters convierten `QgsVectorLayer`, `QgsRasterLayer` y `QgsFeature` en DTOs, WKT, diccionarios y primitivas. 2. **Cómputo (core, sin QGIS)**: servicios y procesadores calculan geología, estructuras, sondajes y perfiles; no tocan objetos QGIS no thread-safe. La novedad es que la frontera también cubre **infraestructura**: - **i18n**: puerto de traducción con fallback identity y adaptador Qt. - **settings**: `SettingsStore` con implementación en memoria y QGIS. - **export**: escritores y `QgsMapSettings` viven en `exporters/`; `ExportService` recibe la factory desde composición. - **logging**: `logger_config` importa QGIS solo cuando usa sus handlers. | Característica | v2.9.0 | v3.11.0 | |---|---|---| | Núcleo QGIS-agnóstico | Parcial (allowlist) | **Sí (allowlist vacía)** | | Tests | 199 | **839 ejecutados / 888 estáticos** | | Módulos >400 líneas | 5 | **0** | | Idiomas de interfaz | 10 | **14 (inglés + 13)** | | QGIS máximo | 3.x | **4.99** | --- ## 🧪 Estabilidad y Calidad ### Suite y gates - **839 tests OK**, **888 tests estáticos**, **131 archivos** de test. - `ruff`, `format`, `mypy` (core + exporters), `check_docs`, `forge validate`, `sync_metrics --validate` e `i18n-check`: PASS. - QGIS 3.28 / Python 3.9 compatible; QGIS 4.2 probado y desplegado. ### Analyzer actual | Métrica | Valor | |---|---:| | Quality / Module Stability | **56.6** | | Maintainability | **99.9** | | Security | **100.0** | | CC gate | **PASS** | | Module size | **PASS (0 >400)** | | Issues | **37** | Desglose de issues: | Tipo | Cantidad | |---|---:| | `GOD_OBJECT` | 20 | | `MISSING_DOCSTRING` | 9 | | `NON_PYTHONIC_LOOP` | 4 | | `POTENTIAL_MISSING_SLOT` | 2 | | `SPAGHETTI_CODE` | 1 | | `UNPRECISE_LAYER` | 1 | El **quality score 56.6** es la media del Maintainability Index por módulo, no una nota de cobertura ni de corrección: está dominado por el tamaño y la complejidad de los módulos. La mantenibilidad (99.9) y la seguridad (100) se miden aparte. ### Deuda conocida - **20 `GOD_OBJECT`**, incluyendo `ProfileController` (21 atributos), diferido. - **9 funciones públicas sin docstring**. - `uv` en Manjaro stable sigue en **0.12.10** (0.13.x está en unstable/Arch). - `Invert line` no implementado; es una feature futura. - Interop §9 (B1) pendiente. - El benchmark `projection_math_performance` puede fallar por timing (0,0501 s vs 0,0500 s) y pasar al repetirse; no es una regresión funcional. --- ## 📈 Conclusión SecInterp v3.11.0 ya no es solo un plugin con “arquitectura limpia” documentada: **la frontera Core/GUI se ejecuta en tests**, los módulos grandes se han descompuesto y la UI refleja mejor los flujos reales (sección → preview → interpretación/export). La base queda preparada para: 1. cerrar la deuda de `GOD_OBJECT` y docstrings; 2. avanzar con interop §9 **B1**; 3. añadir `Invert line` como extensión del selector de sección; 4. mantener `core` sin QGIS como invariante de CI.