Trabajo en tecnología educativa desde 2004; Moodle™ ha sido mi plataforma principal para desarrollar extensiones e integraciones y trabajar sobre sus API y su código base.
Conozco qué API resuelve cada necesidad, dónde termina lo que Moodle™ ya hace y en qué punto una personalización empieza a impedir la siguiente actualización. Cuando decido cómo construir una funcionalidad, puedo estimar también lo que costará mantenerla.
Tomo antes de programar las decisiones que determinan si un desarrollo dura o hay que rehacerlo.
Después de 22 años heredando código ajeno, sé reconocer qué decisiones envejecen mal. Estos son los criterios que aplico en mi trabajo y que reviso cuando audito el de otros.
Uso las API del núcleo antes que cualquier atajo
Uso las interfaces del núcleo de Moodle para el acceso a datos, los formularios, las plantillas, los servicios web, las tareas programadas, los eventos, los permisos, los ficheros, la caché y la privacidad. Accedo a la base de datos mediante la API de Moodle; evito las conexiones directas y las consultas construidas fuera de ella, y reduzco las dependencias innecesarias de las tablas internas del núcleo. También separo la generación de HTML de la lógica. Esos atajos pueden funcionar hoy y dificultar la siguiente actualización.
Responsabilidad única en cada pieza
Separo el acceso a datos, las reglas de negocio y la presentación. Cuando una clase decide, consulta y además dibuja, muchos cambios se propagan a varias responsabilidades y las pruebas pierden capacidad para aislar el fallo.
Patrones solo cuando resuelven un problema
Uso patrones de diseño cuando el problema los pide. Evito fábricas o abstracciones con una sola implementación cuando no aíslan una dependencia, no facilitan las pruebas ni responden a una variación concreta; en esos casos añaden capas intermedias sin reducir el mantenimiento.
Código que se entiende sin su autor delante
Elijo nombres que dicen lo que hacen y escribo funciones breves y cohesionadas, que se entienden de una vez. En los comentarios explico por qué tomé una decisión, no qué hace la línea siguiente. Escribo el código para que el equipo pueda entenderlo dentro de varios años sin depender de que yo siga disponible.
Dónde se concentra la complejidad
Casi siempre me llaman cuando el código que ya existe se ha convertido en el problema.
La plataforma no se puede actualizar, una extensión heredada carece de documentación o el campus se cae el día de más uso. Estos síntomas pueden compartir decisiones deficientes sobre límites y responsabilidades, pero cada uno exige comprobar causas distintas: compatibilidad y actualización, documentación y relevo, o rendimiento y capacidad.
01
Las personalizaciones impiden actualizar la plataforma
He encontrado personalizaciones acumuladas que dependían de detalles internos que habían cambiado. Cada versión nueva obligaba a tratar la actualización como un proyecto completo y la organización terminaba en una versión sin soporte.
02
Nadie documentó el comportamiento del plugin
He revisado un desarrollo sin pruebas ni documentación. El proveedor que lo había creado ya no estaba disponible. El equipo hacía cualquier cambio a ciegas y prefería no tocarlo.
03
El campus se cae en los picos
He encontrado consultas sin índice, llamadas dentro de bucles y procesos que deberían ejecutarse en cola. Según el volumen y el recorrido afectado, cualquiera de esos defectos puede contribuir a una caída justo el día de la matrícula o del examen.
04
Un fallo de permisos deja datos a la vista
Una comprobación de capacidad ausente puede permitir accesos indebidos. Una entrada sin validar aumenta el riesgo durante el recorrido del dato, y una consulta construida por concatenación puede permitir una inyección. Verifico los controles existentes antes de convertir esas señales en hallazgos.
05
Lo que se pide ya lo hace Moodle
Se encarga un desarrollo a medida para algo que el núcleo resuelve con configuración. El resultado cuesta dinero, hay que mantenerlo y además estorba cuando la plataforma incorpora esa función.
06
El LMS acaba haciendo de todo
Cada necesidad de negocio termina dentro de Moodle: facturación, expedientes, seguimiento comercial. La plataforma crece sin límite y ninguna de esas funciones queda donde podría mantenerse mejor.
Qué miro y qué queda por escrito
Qué funcionalidades he construido.
Estos son los tipos de problemas que he tenido que resolver con código y lo que exige cada uno cuando además tiene que funcionar el día de más carga del año.
Evaluación y acreditación por competencias
Marcos de competencias asociados a la actividad real del curso, con las evidencias recogidas allí donde se producen. Lo difícil es conseguir que una misma tarea del alumno genere evidencias válidas para la evaluación, el expediente y la acreditación, sin tener que registrar lo mismo otra vez en cada sistema.
Marcos de competencias
Evidencias asociadas a la actividad
Rúbricas y criterios
Acreditación y credenciales
Expediente del alumno
Biblioteca de contenidos reutilizables
Un fondo común donde el contenido se cataloga, se versiona y se reutiliza en varios cursos sin duplicarse. Lleva permisos por área, control de qué versión está publicada y la posibilidad de corregir en un sitio y que el cambio llegue a todas partes.
Catalogación y metadatos
Versiones y publicación
Reutilización entre cursos
Permisos por área
Formatos y estándares de contenido
Formación adaptativa y metodología aplicada
Itinerarios que cambian según lo que el alumno demuestra, con la condición de que la regla sea explicable a un responsable académico. Aplico el diseño instruccional a lo que la plataforma puede ejecutar: refuerzo, recuperación, secuencias condicionadas y evaluación formativa que sirve para algo más que poner nota.
Itinerarios condicionados
Refuerzo y recuperación
Evaluación formativa
Diseño instruccional aplicado
Reglas explicables
Formación bonificada y obligaciones documentales
Trazabilidad pensada desde el principio para lo que después habrá que justificar: conexiones, tiempos, participación, seguimiento y firmas. Reconstruir esas evidencias a posteriori es caro y a veces imposible, así que el sistema tiene que registrarlas mientras ocurren.
Registro de actividad y tiempos
Seguimiento y tutorización
Documentación justificativa
Exportación para auditoría
Conservación de evidencias
Informes, cuadros de mando e inteligencia de negocio
Indicadores que se pueden rastrear hasta el registro que los origina, extracción periódica hacia el almacén analítico y cuadros de mando por perfil: no necesita lo mismo un tutor que una dirección académica o financiera.
Informes propios
Extracción hacia el almacén analítico
Cuadros de mando por perfil
Indicadores trazables
Alertas con responsable
Automatización de la operación formativa
Procesos automáticos de alta, matriculación, aviso, seguimiento, cierre y certificación, con estados visibles y reanudación controlada tras un fallo. Automatizar un proceso que nadie puede supervisar ni deshacer traslada el trabajo al peor momento.
Procesos programados y en cola
Avisos y seguimiento automático
Estados y reintentos
Certificados y cierres
Supervisión y reversión
Inteligencia artificial dentro del aprendizaje
Acompañamiento sobre el contenido autorizado del curso, apoyo a la corrección y generación de materiales, construidos sobre el subsistema de IA de la plataforma con un proveedor y un punto de integración concretos. La detección temprana de abandono es otra cosa: pertenece al subsistema de analítica, que incorpora un modelo predictivo y necesita datos históricos, entrenamiento y configuración antes de predecir nada. Cada uso lleva fuentes acotadas, permisos, una forma de evaluar su precisión y utilidad, y una persona que responde del resultado.
Respuestas sobre contenido autorizado
Apoyo a la evaluación
Generación de materiales
Modelo predictivo entrenado con datos propios
Evaluación y supervisión humana
Conexión con los sistemas de la organización
Gestión comercial, venta y pagos, sistemas de personal, expedientes y catálogos formativos. Reparto qué dato guarda cada sistema y defino el contrato entre ellos, para que la plataforma de aprendizaje no acabe convertida en el almacén de todo lo que nadie supo dónde poner.
Gestión comercial y venta
Sistemas de personal
Identidad y acceso delegado
Catálogo formativo
Contratos entre sistemas
Responsabilidades concretas
Respondo del código que entra en la plataforma y de lo que costará mantenerlo.
Eso empieza por evitar el desarrollo que no hace falta y sigue por dejar el que sí hace falta con pruebas, permisos revisados y un plan de actualización. Lo que cuesta un plugin se mide en los años que hay que mantenerlo.
01
Decidir qué se construye y qué no
Delimito qué resuelve la configuración del núcleo, qué corresponde a una integración y qué justifica código propio. Cada desarrollo propio que se evita elimina mantenimiento de código a medida, aunque la alternativa —configuración, integración o servicio— también puede tener costes de operación y evolución.
02
Traducir una necesidad formativa a una pieza de software
Una necesidad académica —evaluar por competencias, reutilizar contenido, adaptar el itinerario— admite varias formas de construirse, y no dan el mismo resultado. La que se elija condiciona los permisos, las copias de seguridad y la actualización durante toda la vida del desarrollo.
03
Dejar el desarrollo con pruebas
Pruebas unitarias sobre la lógica y pruebas funcionales sobre el recorrido que hace el usuario. Sin ellas, cada actualización de la plataforma se convierte en una comprobación manual que nadie termina de hacer.
04
Responder de la seguridad
Permisos comprobados en cada acción, parámetros validados por tipo, consultas parametrizadas, salida escapada y protección frente a peticiones falsificadas. También reviso qué datos personales toca el desarrollo y cómo se exportan y se borran.
05
Responder el día de más uso
Reviso consultas e índices, muevo a segundo plano lo que no puede ocurrir durante una petición y uso la caché de la plataforma donde compensa. Antes del despliegue, la prueba relevante reproduce la carga y los recorridos del día de mayor uso.
06
Conectar el LMS con el negocio
Matriculación desde un sistema comercial, pagos, expedientes, catálogos, cuadros de mando. Reparto qué guarda cada sistema y defino contratos entre ellos para que el LMS no acabe siendo el almacén de todo.
Casos de uso
Cómo uso la inteligencia artificial para ir más rápido sin bajar el listón
Las herramientas de IA pueden acelerar algunas tareas de desarrollo; ese posible ahorro no justifica rebajar los criterios de aceptación. Las comprobaciones deterministas detectan fallos reproducibles y la revisión humana decide, con el contexto, si el cambio puede incorporarse.
Entender lo que ya hay
Primero delimitar el código heredado que afecta al cambio
Antes de tocar nada, recupero el contexto real: qué hace cada pieza, quién la llama y qué se rompe si cambia. Aquí puedo ahorrar mucho tiempo, pero también equivocarme si doy por supuesto cómo funciona el código.
Búsqueda contextual en el código
Mapa de dependencias
Rastreo de quién usa qué
Documentación del comportamiento actual
Acotar las fuentes
Las respuestas deben poder verificarse en fuentes autorizadas
Le proporciono únicamente documentación oficial de la versión declarada y las convenciones del proyecto. No acepto una respuesta que no pueda verificarse en esas fuentes: debe citarlas, y el sistema se abstiene cuando no encuentra respaldo suficiente. La evaluación comprueba tanto la atribución como los casos en los que debe callarse.
Documentación oficial como fuente
Convenciones del proyecto
Versión declarada, no supuesta
Sin respuesta cuando no hay fuente
Escribir
Generación con el contexto justo
La calidad de lo que sale depende de lo acotado que esté el encargo. Delimito el problema, doy los ejemplos del propio proyecto y pido el cambio mínimo, en lugar de encargar una funcionalidad completa y revisar después un bloque que nadie entiende.
Encargo delimitado
Ejemplos del propio proyecto
Cambio mínimo
Estilo del código existente
Comprobar sin opinión
Reglas deterministas sobre la estructura del código
Aquí no interviene el modelo. Analizo el árbol sintáctico del código y aplico reglas deterministas: ante la misma entrada producen el mismo resultado y permiten localizar comprobaciones de permisos ausentes, parámetros sin validar, consultas construidas por concatenación o usos indebidos de las interfaces de la plataforma. Cada alerta conserva la regla y la evidencia que la originan; después se contrasta con el contexto para descartar falsos positivos antes de convertirla en un hallazgo.
Análisis del árbol sintáctico
Reglas de seguridad
Uso correcto de las interfaces
Resultado repetible
Revisar
Varias pasadas, cada una con una lente distinta
Una sola revisión encuentra lo evidente. Reviso por separado la seguridad, la corrección, el rendimiento y la capacidad de mantenerlo, porque cada mirada ve lo que las otras dejan pasar. Siempre que el equipo lo permite, otra persona revisa el cambio. Cuando trabajo solo, separo la escritura de esas pasadas, dejo transcurrir tiempo y registro cada hallazgo con su evidencia. Esa separación reduce errores, pero no equivale a una revisión independiente.
Pasadas por dimensión
Revisión adversarial
Separación entre escribir y revisar
Hallazgos con cita exacta
Demostrar
Nada entra sin una prueba que pueda fallar
El código asistido llega con pruebas, y la pregunta es siempre la misma: si rompo esto a propósito, ¿la prueba se entera? Una prueba que pasa haga lo que haga el código puede crear una confianza falsa y ocultar la falta real de cobertura.
Pruebas que detectan una rotura
Comprobación por mutación
Recorrido funcional completo
Ejecución en cada cambio
Cómo trabajo
Cada desarrollo pasa por el mismo recorrido, desde el problema hasta el procedimiento de reversión.
No empiezo por el código. Empiezo por comprobar si el núcleo ya resuelve el problema, porque el trabajo que se evita no hay que mantenerlo después.
01
Delimitar el problema
Concreto qué debe ocurrir, para quién y en qué casos excepcionales. Después compruebo si el núcleo ya lo resuelve antes de aceptar que hace falta código.
02
Diseñar la pieza
Elijo el tipo de extensión, los límites con el resto del sistema, el modelo de datos y los permisos. Aquí se decide casi todo lo que costará mantener.
03
Construir con pruebas
Escribo la lógica separada de la presentación y la cubro con pruebas que fallan cuando se rompe el comportamiento, no cuando cambia un texto.
04
Revisar antes de desplegar
Reviso permisos, validación de entrada, escapado de salida y consultas. Compruebo el comportamiento con volumen y no solo con tres registros de ejemplo.
05
Dejarlo mantenible
Entrego con documentación, procedimiento de instalación y de reversión, y el criterio con el que se decidió cada cosa, para que el equipo pueda continuar sin mí.
Experiencia y trabajo propio
Sigo programando, y por eso puedo defender cada decisión de arquitectura con el código delante.
Más de 22 años escribiendo y revisando código, con Moodle como plataforma principal.
Cualificación oficial de Moodle en administración de la plataforma (Moodle Administrator Qualification, MAQ).
Programas de desarrollo de Moodle Academy: Moodle Developer Basics y Moodle Developer Skills.
Herramientas propias de análisis automatizado de extensiones de Moodle, que aplican reglas de seguridad, estilo y uso correcto de las API.
Trabajo habitual de revisión de código ajeno: localizo los usos indebidos de las API, los riesgos de permisos y las decisiones que impedirán actualizar.
Desarrollo sobre PHP en la plataforma, y sobre Python, Node y JavaScript en los sistemas que la rodean.
Trabajo propio relacionado
Mis herramientas propias sobre calidad y diagnóstico de Moodle muestran cómo reviso el código.
Documentan las reglas que aplico al revisar una extensión y lo que busco antes de aceptar un desarrollo. El trabajo hecho para otras organizaciones no aparece por confidencialidad.
En el blog escribo sobre el desarrollo de Moodle con el detalle que aquí no cabe.
Allí entro en decisiones concretas: cuándo un plugin deja de ser mantenible, cómo se prueba una extensión en condiciones reales, qué revisar en el código que hereda un equipo y qué separa una personalización razonable de una que hipoteca la plataforma.