Tema 46. Lenguajes de programación. Características. Fundamentos. Traductores, compiladores, ensambladores e intérpretes. Estado del arte de las técnicas, herramientas y entornos de desarrollo: entornos visuales, JAVA, .NET, Python, lenguajes de scripting.

30 min agosto 5, 2026 Media Nuevo

Tabla de contenidos

Tema 46. Lenguajes de programación. Características. Fundamentos. Traductores, compiladores, ensambladores e intérpretes. Estado del arte de las técnicas, herramientas y entornos de desarrollo: entornos visuales, JAVA, .NET, Python, lenguajes de scripting.

Fundamentos de los lenguajes, mecanismos de traducción y plataformas modernas de desarrollo para sistemas de información
Oposición: Técnico/a de Función Administrativa, Sistemas y Tecnología de la Información – Servicio Andaluz de Salud (SAS)
Bloque: Temario Específico | Última actualización: Agosto 2026
Preparador: Esteban Castro | Material basado en exámenes oficiales SAS

1. INTRODUCCIÓN Y ENCUADRE

Un lenguaje de programación es un sistema formal utilizado para describir algoritmos, estructuras de datos, reglas de negocio e interacciones con un entorno de ejecución. No debe confundirse con una mera notación para escribir instrucciones: un lenguaje define una sintaxis, una semántica y un modelo de ejecución, y se integra en una cadena de herramientas que transforma el programa escrito por una persona en operaciones realizables por una máquina. En un sistema de información sanitario, el lenguaje elegido condiciona la mantenibilidad, la seguridad, la capacidad de integración, el rendimiento y la facilidad con que el sistema puede evolucionar durante años.

El temario reúne dos planos que conviene estudiar conjuntamente. El primero es conceptual: características de los lenguajes, tipos, fundamentos, traductores, compiladores, ensambladores e intérpretes. El segundo es tecnológico: Java, .NET, Python, lenguajes de scripting, entornos visuales y herramientas modernas de desarrollo. Separarlos en exceso conduce a errores. Java no se entiende sin la máquina virtual y el bytecode; .NET no se entiende sin CIL, metadatos, CLR y compilación JIT; Python no se comprende correctamente si se reduce a la etiqueta «interpretado»; y JavaScript actual no puede explicarse ignorando los motores con compilación dinámica, los módulos y la ejecución tanto en navegador como en servidor.

Desde el punto de vista de una oposición técnica A1, la cuestión esencial no es memorizar una lista de productos, sino dominar las distinciones estructurales: código fuente frente a código objeto; compilación frente a interpretación; lenguaje frente a implementación; bytecode frente a código máquina; tipado estático frente a tipado dinámico; gestión manual frente a automática de memoria; biblioteca frente a framework; editor frente a entorno integrado de desarrollo; y compilación anticipada frente a compilación justo a tiempo. Estas oposiciones suelen construir distractores mezclando conceptos cercanos, por lo que el estudio debe centrarse en el criterio que separa cada pareja.

Idea central: un lenguaje no determina por sí solo cómo se ejecuta un programa. La misma especificación puede tener distintas implementaciones: intérpretes, compiladores a código nativo, compiladores a bytecode o combinaciones con JIT y AOT. Por ello, afirmar que un lenguaje «es compilado» o «es interpretado» suele ser una simplificación; técnicamente debe describirse la implementación y su cadena de ejecución.

En el contexto del Servicio Andaluz de Salud y de la Junta de Andalucía, la elección tecnológica no puede responder únicamente a preferencias personales. Debe alinearse con la arquitectura corporativa, la interoperabilidad, la seguridad, la protección de datos, la accesibilidad, la disponibilidad de soporte, la capacitación de los equipos y el ciclo de vida del producto. Una aplicación clínica o administrativa puede permanecer en explotación durante décadas; por ello, la estabilidad del ecosistema, la compatibilidad hacia atrás, la observabilidad, la automatización de pruebas y la gestión de vulnerabilidades pesan tanto como la productividad inicial.

Este tema presenta primero los fundamentos de los lenguajes y los mecanismos de traducción. A continuación analiza Java, .NET, Python y los principales lenguajes de scripting. Finalmente estudia los entornos visuales, las herramientas de construcción, la integración continua, la seguridad de la cadena de suministro y las tendencias actuales: compilación AOT, WebAssembly, contenedores de desarrollo, servidores de lenguaje, desarrollo asistido por inteligencia artificial, plataformas internas para desarrolladores y enfoques low-code. El objetivo es que puedas relacionar cada tecnología con su modelo de ejecución y seleccionar razonadamente la alternativa más adecuada.

2. CARACTERÍSTICAS Y FUNDAMENTOS DE LOS LENGUAJES

2.1. Sintaxis, semántica y pragmática

La sintaxis establece qué secuencias de símbolos forman programas válidos. Se describe mediante gramáticas formales, normalmente variantes de BNF o EBNF. La sintaxis permite reconocer elementos léxicos —identificadores, literales, palabras reservadas, operadores— y construir estructuras superiores, como expresiones, sentencias, declaraciones, clases o módulos. Un programa puede ser sintácticamente correcto y, sin embargo, carecer de sentido: por ejemplo, aplicar una operación aritmética a valores incompatibles o invocar una función con parámetros incorrectos.

La semántica determina el significado de las construcciones. Incluye las reglas de tipos, el alcance de los identificadores, el orden de evaluación, la gestión de excepciones, la creación y destrucción de objetos y los efectos observables de cada operación. Puede describirse de forma operacional —mediante pasos de ejecución—, denotacional —asociando construcciones con objetos matemáticos— o axiomática —mediante precondiciones y postcondiciones—. En la práctica, las especificaciones de los lenguajes combinan lenguaje formal y prosa normativa.

La pragmática se refiere a la forma en que el lenguaje favorece o dificulta determinados usos: legibilidad, expresividad, disponibilidad de bibliotecas, calidad de herramientas, facilidad de depuración, rendimiento, seguridad y adecuación al dominio. Dos lenguajes pueden ser computacionalmente equivalentes y, sin embargo, resultar muy distintos para construir un sistema distribuido, procesar datos clínicos o automatizar tareas de administración.

2.2. Abstracción, expresividad y ortogonalidad

La abstracción permite ocultar detalles irrelevantes y trabajar con conceptos de mayor nivel. Las funciones abstraen secuencias de operaciones; las clases encapsulan estado y comportamiento; los módulos delimitan interfaces; los tipos algebraicos representan variantes de datos; y las corrutinas abstraen flujos asíncronos. Un nivel de abstracción elevado aumenta la productividad y la portabilidad, pero no elimina la necesidad de comprender el coste de las operaciones ni el comportamiento del runtime.

La expresividad mide, de manera informal, la facilidad con que un lenguaje representa una solución. No equivale a escribir menos caracteres. Un lenguaje expresivo permite formular invariantes, contratos o transformaciones de datos con claridad. La ortogonalidad indica hasta qué punto las características se combinan de forma regular, con pocas excepciones. La ortogonalidad reduce la carga cognitiva, aunque un diseño excesivamente general puede complicar la implementación o el aprendizaje.

2.3. Sistema de tipos

Un tipo define un conjunto de valores y las operaciones permitidas sobre ellos. El tipado puede ser estático, cuando gran parte de la comprobación se realiza antes de ejecutar; o dinámico, cuando los valores llevan información de tipo y las comprobaciones se efectúan durante la ejecución. Esta distinción no coincide con «compilado» e «interpretado». Java y C# son predominantemente estáticos, mientras que Python y JavaScript son dinámicos; todos ellos pueden utilizar compilación y máquinas virtuales.

También se distingue entre tipado fuerte y débil, aunque no existe una definición universal. En general, un sistema fuerte limita conversiones implícitas peligrosas y mantiene invariantes de tipo. Otros conceptos relevantes son la inferencia de tipos, los genéricos, la varianza, la nulabilidad, los tipos unión, los tipos dependientes y el tipado gradual. TypeScript y las anotaciones de Python muestran un enfoque gradual: se añaden comprobaciones estáticas sobre lenguajes cuyo runtime continúa siendo dinámico.

Criterio Alternativas Consecuencia principal
Momento de comprobación Estático / dinámico Detección temprana frente a flexibilidad en ejecución.
Disciplina de conversión Más fuerte / más permisiva Menor ambigüedad frente a mayor coerción automática.
Declaración Explícita / inferida Verbocidad frente a deducción por el compilador.
Mutabilidad Mutable / inmutable Facilidad de actualización frente a razonamiento y concurrencia más seguros.
Nulabilidad Implícita / expresada en el tipo Riesgo de referencias nulas frente a comprobación explícita.

2.4. Ámbito, enlace y tiempo de vida

El ámbito indica dónde es visible un nombre. Puede ser léxico, determinado por la estructura del texto fuente, o dinámico, determinado por la cadena de llamadas. El enlace o binding asocia nombres con entidades: variables, funciones, tipos o módulos. Puede producirse en compilación, enlace, carga o ejecución. El tiempo de vida de un objeto es el periodo durante el que existe en memoria y no debe confundirse con el ámbito del nombre que lo referencia.

La asignación de memoria puede realizarse en zona estática, pila o montón. La pila favorece una gestión automática ligada a llamadas y bloques; el montón permite objetos con vida independiente, pero requiere liberación. C y C++ permiten gestión manual y determinista; Java, .NET, Python y JavaScript usan recolección automática de basura, aunque mantienen recursos externos —archivos, conexiones, sockets— que deben cerrarse mediante patrones específicos. La recolección automática reduce ciertos errores, pero no impide fugas lógicas, retención involuntaria o agotamiento de recursos.

Trampa de examen: tipado estático no significa necesariamente declaración explícita, y recolección de basura no significa ausencia de fugas. Un compilador puede inferir tipos estáticos; un runtime con garbage collector puede conservar objetos alcanzables que la aplicación ya no necesita.

2.5. Control, modularidad y concurrencia

Los lenguajes incorporan estructuras de control secuencial, selección, iteración, recursión, excepciones y, cada vez más, abstracciones asíncronas. La modularidad se materializa mediante procedimientos, módulos, paquetes, clases, componentes y servicios. Una buena interfaz oculta decisiones internas y reduce el acoplamiento. La reutilización eficaz exige contratos claros, versionado semántico, pruebas y compatibilidad; copiar código no es reutilización arquitectónica.

La concurrencia puede expresarse con hilos, procesos, actores, tareas, eventos, corrutinas o flujos reactivos. Cada modelo introduce riesgos distintos: condiciones de carrera, interbloqueos, inanición, pérdida de mensajes o desbordamiento de colas. Los lenguajes modernos intentan elevar el nivel de abstracción con async/await, concurrencia estructurada, inmutabilidad y canales. En sistemas sanitarios, donde la trazabilidad y la consistencia son esenciales, debe priorizarse un modelo comprensible y verificable sobre la sofisticación innecesaria.

3. CLASIFICACIÓN DE LOS LENGUAJES Y PARADIGMAS

3.1. Por nivel de abstracción

El código máquina está formado por instrucciones codificadas para una arquitectura concreta. Es el nivel ejecutado directamente por el procesador. El ensamblador sustituye las codificaciones binarias por mnemónicos, etiquetas y directivas, pero continúa ligado al repertorio de instrucciones, registros, modos de direccionamiento y convenciones de la plataforma. Los lenguajes de alto nivel abstraen estos detalles y proporcionan tipos, estructuras de control, módulos y bibliotecas.

No existe una frontera absoluta entre «bajo» y «alto» nivel. C ofrece abstracciones portables, pero permite operar con punteros y representación de memoria; Rust proporciona control cercano al sistema con un modelo de propiedad orientado a seguridad; Java y C# se apoyan en runtimes gestionados; Python prioriza productividad y reflexión dinámica. El nivel de abstracción debe analizarse respecto de la máquina y del dominio del problema.

NIVELES DE REPRESENTACIÓN

├── Código fuente de alto nivel
│ ├── tipos, módulos, clases, funciones
│ └── independiente en gran medida del procesador

├── Representación intermedia
│ ├── AST / IR del compilador
│ ├── bytecode JVM
│ └── CIL de .NET

├── Ensamblador
│ ├── mnemónicos y etiquetas
│ └── específico de ISA y ABI

└── Código máquina
├── instrucciones binarias
└── ejecutable por una arquitectura concreta

3.2. Por propósito

Los lenguajes de propósito general permiten abordar múltiples dominios. Otros se orientan a sistemas, consulta de datos, cálculo científico, descripción de hardware, reglas, transformación de documentos o configuración. SQL es declarativo y especializado en datos relacionales; expresiones regulares describen patrones; lenguajes de infraestructura como código declaran recursos; y los lenguajes de sombreado programan etapas gráficas. Un lenguaje específico de dominio puede aumentar precisión y productividad, pero introduce dependencia de herramientas y conocimiento especializado.

3.3. Paradigmas

El paradigma imperativo describe cambios de estado mediante instrucciones. La programación estructurada organiza el control con secuencia, selección e iteración. La orientación a objetos modela entidades mediante objetos, encapsulación, herencia y polimorfismo. La programación funcional favorece funciones puras, composición, inmutabilidad y evaluación de expresiones. La programación lógica declara hechos y reglas. La programación orientada a eventos reacciona a sucesos y es común en interfaces, sistemas distribuidos y runtimes de JavaScript.

Los lenguajes actuales son habitualmente multiparadigma. Java incorpora expresiones lambda y streams; C# combina orientación a objetos, consultas integradas y programación funcional; Python soporta objetos, funciones de orden superior, generadores y metaprogramación; JavaScript combina prototipos, cierres, eventos y funciones de primera clase. En una pregunta tipo test, no debe confundirse «admitir» un paradigma con estar diseñado principalmente alrededor de él.

Paradigma Unidad central Ventaja habitual Riesgo típico
Imperativo Estado e instrucciones Correspondencia directa con el algoritmo Efectos laterales difíciles de controlar
Orientado a objetos Objetos y mensajes Encapsulación y extensibilidad Jerarquías rígidas y acoplamiento
Funcional Funciones y valores Razonamiento, composición y concurrencia Abstracción excesiva o costes ocultos
Declarativo Resultado o relación Separación entre qué y cómo Menor control sobre el plan de ejecución
Orientado a eventos Eventos y manejadores Interactividad y desacoplamiento temporal Flujos difíciles de seguir sin disciplina

3.4. Generaciones y etiquetas históricas

Las denominaciones 1GL, 2GL, 3GL, 4GL y 5GL son históricas y no constituyen una taxonomía técnica uniforme. Suele asociarse 1GL con código máquina, 2GL con ensamblador, 3GL con lenguajes de alto nivel, 4GL con lenguajes declarativos o generadores de aplicaciones y 5GL con enfoques basados en restricciones o inteligencia artificial. Deben usarse con cautela porque agrupan tecnologías heterogéneas y pueden variar según la fuente.

Recuerda: «lenguaje de scripting» tampoco es una categoría formal cerrada. Describe, sobre todo, un modo de uso ligado a automatización, integración y ejecución mediante un host. JavaScript, Python, Bash, PowerShell y PHP pueden utilizarse en proyectos grandes, por lo que el tamaño del programa no define por sí solo si es un script.

4. TRADUCTORES: CONCEPTO Y TAXONOMÍA

4.1. El traductor dentro de la cadena de herramientas

Un traductor recibe un programa en un lenguaje fuente y produce una representación en un lenguaje destino, preservando su comportamiento según las reglas definidas. El destino puede ser código máquina, ensamblador, bytecode, CIL, otro lenguaje de alto nivel o una representación intermedia. La traducción suele acompañarse de diagnóstico de errores, información de depuración, metadatos y artefactos necesarios para enlazar o cargar el programa.

La cadena real incluye más elementos que el compilador. El preprocesador transforma el texto antes del análisis; el ensamblador convierte ensamblador en código objeto; el enlazador resuelve símbolos entre módulos y bibliotecas; el cargador sitúa el ejecutable en memoria; el runtime inicializa el entorno; y un compilador JIT puede generar código nativo durante la ejecución. En ecosistemas gestionados, el compilador de lenguaje genera una representación intermedia y el runtime completa la transformación.

4.2. Compilador

Un compilador analiza una unidad de programa y genera otra representación antes o durante la ejecución. La definición no exige producir un ejecutable nativo ni procesar «todo el programa de una vez». Existen compiladores incrementales, por métodos, módulos o funciones; compiladores JIT; compiladores de consulta; y compiladores que emiten otro lenguaje. Lo esencial es la traducción sistemática y el análisis del programa, no una oposición rígida a la interpretación.

4.3. Intérprete

Un intérprete ejecuta una representación del programa sin producir necesariamente un ejecutable persistente. Puede recorrer un árbol sintáctico, ejecutar bytecode, aplicar reglas o delegar partes a un JIT. La imagen didáctica de «leer, traducir y ejecutar línea por línea» solo describe algunos intérpretes sencillos. CPython compila primero a bytecode; los motores JavaScript analizan, generan representaciones internas y optimizan dinámicamente; y las shells procesan construcciones completas con expansión, redirecciones y tuberías.

4.4. Ensamblador, transpilador y compilador cruzado

El ensamblador traduce lenguaje ensamblador a código objeto o máquina. La correspondencia entre instrucción fuente e instrucción máquina no siempre es uno a uno: existen pseudoinstrucciones, macros, directivas y expansiones dependientes del ensamblador. Un transpilador traduce entre lenguajes de nivel semejante; TypeScript a JavaScript es un ejemplo conocido. Un compilador cruzado se ejecuta en una plataforma anfitriona y genera código para otra plataforma objetivo, práctica habitual en sistemas embebidos y compilación para arquitecturas diferentes.

Herramienta Entrada Salida o efecto Ejemplo conceptual
Preprocesador Texto fuente Texto transformado Inclusión o expansión condicional
Compilador Lenguaje fuente Código objeto, IR, bytecode u otro lenguaje Java a class; C# a CIL
Ensamblador Ensamblador Código objeto Mnemónicos de una ISA a bytes
Enlazador Objetos y bibliotecas Ejecutable o biblioteca Resolución de símbolos
Intérprete Fuente, AST o bytecode Ejecución Máquina de bytecode de CPython
Transpilador Lenguaje de alto nivel Otro lenguaje de alto nivel TypeScript a JavaScript
Perla real: en el examen TFA STI SAS 2019, turno libre, pregunta 84, se preguntó la diferencia entre código binario y bytecode. El criterio correcto era que el bytecode es el resultado intermedio de ciertos lenguajes que utilizan una máquina virtual, mientras que el código máquina es específico de una arquitectura y ejecutable por su procesador.

4.5. Errores y diagnóstico

Los errores pueden aparecer en distintas fases. Un error léxico contiene símbolos no reconocidos; uno sintáctico viola la gramática; uno semántico infringe reglas de tipos, nombres o contratos; uno de enlace deja símbolos sin resolver; y uno de ejecución surge con valores concretos o condiciones del entorno. Los compiladores modernos intentan recuperar contexto para informar de varios errores en una ejecución, pero un diagnóstico posterior puede ser consecuencia del primero. La depuración exige identificar la fase en la que se origina el problema.

Trampa: «compilado» no equivale a «sin errores en ejecución». La compilación detecta una clase de defectos, pero no puede anticipar todos los datos de entrada, fallos de red, agotamiento de recursos, condiciones de carrera o vulnerabilidades lógicas.

5. ARQUITECTURA Y FASES DE UN COMPILADOR

5.1. Front-end, middle-end y back-end

La arquitectura clásica separa el front-end, que comprende el lenguaje fuente; el middle-end, que opera sobre representaciones intermedias y optimizaciones; y el back-end, que conoce la arquitectura o formato destino. Esta separación permite reutilizar un mismo front-end para varios objetivos o un mismo back-end para distintos lenguajes. Infraestructuras como LLVM popularizan una representación intermedia común, aunque cada compilador mantiene decisiones específicas.

COMPILADOR

├── FRONT-END
│ ├── análisis léxico → tokens
│ ├── análisis sintáctico → árbol
│ ├── análisis semántico → tipos y nombres
│ └── diagnóstico

├── MIDDLE-END
│ ├── representación intermedia
│ ├── análisis de flujo
│ └── optimizaciones independientes de máquina

└── BACK-END
├── selección de instrucciones
├── asignación de registros
├── planificación
└── emisión de código objeto / bytecode

5.2. Análisis léxico

El analizador léxico agrupa caracteres en tokens: palabras reservadas, identificadores, literales, operadores y signos. Ignora o conserva comentarios y espacios según el lenguaje. Se apoya en autómatas finitos y expresiones regulares. Debe resolver casos como operadores de varios caracteres, literales escapados y palabras que comparten prefijo. La tabla de símbolos empieza a recoger nombres y atributos, aunque su gestión continúa en fases posteriores.

total = precio * unidades;

IDENT(total)  ASSIGN  IDENT(precio)  MUL  IDENT(unidades)  SEMICOLON

5.3. Análisis sintáctico

El parser comprueba que la secuencia de tokens pertenece al lenguaje definido por la gramática y construye un árbol sintáctico concreto o abstracto. El AST elimina detalles de puntuación y conserva la estructura significativa. Los analizadores pueden ser descendentes, ascendentes, predictivos o generados a partir de gramáticas. La precedencia y asociatividad de operadores determinan cómo se agrupan las expresiones.

Asignación
├── destino: total
└── valor: Multiplicación
    ├── precio
    └── unidades

5.4. Análisis semántico

El análisis semántico resuelve identificadores, comprueba visibilidad, tipos, parámetros, conversiones y reglas contextuales que la gramática no expresa fácilmente. Puede construir tablas de símbolos y anotar el AST con tipos. En lenguajes con genéricos, sobrecarga o inferencia, esta fase puede ser compleja. Un error típico es confundir sintaxis y semántica: 3 + verdadero puede tener forma sintáctica válida, pero ser semánticamente inválido si el lenguaje no define esa operación.

5.5. Representación intermedia

La representación intermedia o IR ofrece una forma adecuada para análisis y optimización. Puede ser de alto nivel, cercana al AST; de nivel medio, con operaciones independientes de la máquina; o de bajo nivel, próxima al conjunto de instrucciones. El código de tres direcciones simplifica expresiones complejas en operaciones elementales. Formas como SSA asignan cada variable una sola vez y facilitan el análisis de flujo de datos.

t1 = precio * unidades
t2 = t1 - descuento
total = t2

5.6. Optimización

Optimizar significa mejorar alguna propiedad —tiempo, tamaño, consumo, accesos a memoria— sin cambiar el comportamiento observable permitido. Entre las técnicas se encuentran propagación de constantes, eliminación de código muerto, simplificación algebraica, inlining, desenrollado de bucles, vectorización y optimización guiada por perfiles. No toda transformación reduce el tiempo en todos los equipos; por eso existen niveles de optimización y decisiones dependientes del objetivo.

La optimización se limita por efectos laterales, aliasing, excepciones, concurrencia y reglas de precisión numérica. Reordenar operaciones de coma flotante puede cambiar resultados. El compilador debe respetar el modelo de memoria del lenguaje y no puede eliminar operaciones observables. En código crítico, la medición mediante perfiles es preferible a suposiciones.

5.7. Generación de código

El back-end selecciona instrucciones, asigna registros, organiza la pila, respeta la ABI y emite código objeto, bytecode o ensamblador. La ABI define convenciones binarias: llamada a funciones, paso de parámetros, uso de registros, alineación, formato de objetos y nombres de símbolos. La compatibilidad de código fuente no garantiza compatibilidad binaria; una biblioteca puede mantener la API y romper la ABI.

5.8. Compilación incremental y cachés

Los proyectos modernos son demasiado grandes para recompilarse completamente en cada cambio. La compilación incremental identifica unidades afectadas y reutiliza artefactos. Las herramientas de construcción calculan grafos de dependencias, hashes y cachés locales o remotas. El reto es evitar dependencias ocultas y asegurar que la salida sea reproducible. Una caché incorrecta puede generar resultados obsoletos difíciles de diagnosticar.

Fase Entrada Salida Error característico
Léxica Caracteres Tokens Literal o símbolo no válido
Sintáctica Tokens Árbol Estructura no admitida por la gramática
Semántica Árbol y símbolos Árbol tipado Tipo incompatible o nombre no resuelto
IR Árbol tipado Representación intermedia Fallo interno del compilador
Optimización IR IR optimizada Transformación no válida si el compilador tiene un defecto
Generación IR Objeto, bytecode o ensamblador Objetivo no compatible
Enlace Objetos y bibliotecas Ejecutable o biblioteca Símbolo no definido o duplicado
Para memorizar: análisis léxico produce tokens; análisis sintáctico produce una estructura; análisis semántico añade significado contextual; la optimización transforma una IR; y la generación produce el formato objetivo.

6. ENSAMBLADORES, ENLAZADORES Y CARGADORES

6.1. Lenguaje ensamblador

El lenguaje ensamblador representa instrucciones de una arquitectura mediante mnemónicos y operandos simbólicos. Está ligado a una ISA —arquitectura del repertorio de instrucciones— como x86-64 o AArch64, pero también a la sintaxis del ensamblador y a la ABI del sistema. Dos ensambladores pueden utilizar sintaxis distintas para la misma ISA. El código necesita conocer registros, tamaños, modos de direccionamiento, pila y convenciones de llamada.

Su utilidad actual se concentra en arranque, controladores, firmware, rutinas muy específicas, criptografía, cambios de contexto, análisis de malware y fragmentos donde es necesario utilizar instrucciones no expuestas por el lenguaje de alto nivel. Sin embargo, no debe suponerse que escribir ensamblador produce automáticamente mejor rendimiento. Los compiladores optimizadores disponen de análisis globales, vectorización y conocimiento del microprocesador; el ensamblador manual puede impedir optimizaciones o introducir dependencias deficientes.

6.2. Código objeto y reubicación

El ensamblador suele producir un archivo objeto, no un ejecutable final. El objeto contiene secciones de código y datos, símbolos, información de reubicación y, en su caso, depuración. Las referencias cuyo destino aún no se conoce quedan pendientes. La reubicación permite ajustar direcciones cuando los módulos se sitúan en el espacio de memoria definitivo.

6.3. Enlace estático y dinámico

El enlazador combina objetos y bibliotecas, resuelve símbolos y genera un ejecutable o biblioteca. En el enlace estático, el código necesario se incorpora al artefacto final. Esto facilita despliegues autocontenidos, pero aumenta tamaño y obliga a reconstruir para incorporar correcciones. En el enlace dinámico, el ejecutable referencia bibliotecas compartidas que se resuelven en carga o ejecución. Reduce duplicación y permite actualizar componentes, pero introduce dependencias de versión y riesgos de incompatibilidad.

La resolución dinámica puede ser temprana o diferida. El cargador mapea segmentos, aplica reubicaciones, resuelve dependencias, prepara pila y entorno e inicia el punto de entrada. Mecanismos como ASLR cambian ubicaciones para dificultar explotación. En runtimes gestionados, además, se cargan ensamblados, clases o módulos con metadatos y reglas de aislamiento.

6.4. Macros y pseudoinstrucciones

Una macro expande texto o patrones antes del ensamblado. Una pseudoinstrucción puede traducirse a una o varias instrucciones reales. Por ello, la afirmación «una línea de ensamblador equivale siempre a una instrucción máquina» es falsa. También existen directivas que reservan memoria, alinean secciones o declaran símbolos y no corresponden a una instrucción ejecutada.

Trampa: ensamblador es el lenguaje; ensamblador también puede designar la herramienta traductora según el contexto. El resultado habitual es código objeto que todavía debe enlazarse, no necesariamente un ejecutable listo para usar.

6.5. Desensamblado y depuración

Un desensamblador reconstruye una representación ensambladora desde bytes, pero no recupera el código fuente original, nombres, tipos ni intención. La información de depuración y símbolos mejora el resultado. En investigación de incidencias, comprender una traza nativa o un volcado puede revelar violaciones de memoria, instrucciones ilegales o fallos en bibliotecas. Para la mayoría de aplicaciones administrativas, no se programa directamente en ensamblador, pero conocer esta capa ayuda a interpretar el funcionamiento de compiladores y runtimes.

7. INTÉRPRETES, MÁQUINAS VIRTUALES, JIT Y AOT

7.1. Estrategias de interpretación

Un intérprete puede ejecutar directamente el árbol sintáctico, traducirlo a bytecode para una máquina virtual o combinar varias estrategias. La interpretación de AST es sencilla, pero puede tener mayor coste por nodo. El bytecode codifica operaciones compactas y permite un bucle de despacho más eficiente. Las máquinas de bytecode pueden basarse en pila o registros. La elección afecta a densidad, complejidad y facilidad de optimización.

La interpretación aporta interactividad, portabilidad y capacidad de introspección. Facilita REPL, carga dinámica y metaprogramación. Sus costes provienen del despacho repetido, comprobaciones dinámicas y menor especialización. Sin embargo, una comparación de rendimiento no puede basarse solo en la etiqueta del lenguaje: bibliotecas nativas, vectorización, JIT, cachés y patrón de carga dominan a menudo el resultado.

7.2. Máquina virtual

Una máquina virtual de proceso define una arquitectura abstracta para ejecutar programas, como JVM o CLR. No emula necesariamente un equipo completo. Proporciona carga de módulos, verificación, gestión de memoria, excepciones, hilos, reflexión y servicios de interoperabilidad. El mismo bytecode puede ejecutarse en plataformas con una implementación compatible del runtime, aunque la portabilidad real también depende de bibliotecas, sistema de archivos, codificación, zona horaria y recursos externos.

7.3. Compilación JIT

El compilador Just-In-Time genera código nativo durante la ejecución. Puede compilar un método al primer uso o después de detectar que es «caliente». La compilación por niveles empieza con código rápido de generar y recompila partes frecuentes con optimizaciones más costosas. Los perfiles dinámicos permiten especializar según tipos, ramas y llamadas observadas. Si cambian las hipótesis, el runtime puede desoptimizar y volver a una representación segura.

El JIT ofrece buen rendimiento sostenido, pero añade calentamiento, consumo de memoria y variabilidad. En procesos cortos, funciones serverless o herramientas de línea de comandos, el tiempo de arranque puede ser relevante. En servicios de larga duración, la optimización adaptativa puede superar a un binario AOT que carece de información del comportamiento real.

7.4. Compilación AOT

La compilación Ahead-Of-Time produce código nativo antes del despliegue. Mejora arranque, reduce la necesidad de compilar en producción y puede disminuir la superficie del runtime. A cambio, puede limitar reflexión y carga dinámica, aumentar el tiempo de construcción y requerir configuración para conservar elementos usados indirectamente. Java dispone de alternativas de imagen nativa y .NET ofrece Native AOT para determinados escenarios; Python puede empaquetarse o compilarse mediante herramientas específicas, aunque no todas eliminan el runtime.

7.5. Bytecode frente a binario nativo

El bytecode es una representación para una máquina abstracta; el binario nativo contiene instrucciones para una ISA real. El bytecode no es simplemente «código fuente comprimido». Puede incorporar metadatos, tablas y formatos verificables. Los archivos Java .class contienen bytecode JVM; los ensamblados .NET contienen CIL y metadatos; CPython utiliza bytecode interno, cacheado habitualmente en archivos .pyc, cuyo formato puede cambiar entre versiones.

Perla real: la pregunta 85 del examen TFA STI SAS 2019 planteó si un script Python podía compilarse para obtener código binario y no solo bytecode. La respuesta aceptada fue que existen herramientas e incluso distribuciones que lo permiten. La enseñanza es que «Python interpretado» no excluye compilación, empaquetado o generación nativa.
Estrategia Cuándo traduce Ventajas Costes
Interpretación Durante ejecución Interactividad y flexibilidad Despacho y comprobaciones repetidas
Bytecode + VM Fuente antes; bytecode en runtime Portabilidad y servicios gestionados Dependencia del runtime
JIT Durante ejecución, según uso Optimización adaptativa Calentamiento y variabilidad
AOT Antes del despliegue Arranque y binario nativo Menor dinamismo y build más complejo

7.6. Lenguaje, implementación y distribución

Python es un lenguaje con implementaciones como CPython y PyPy; Java es un lenguaje, una plataforma y un conjunto de especificaciones con distintas JVM; C# es un lenguaje que suele dirigirse a .NET; JavaScript se ejecuta en motores integrados en hosts. La distribución puede ser fuente, bytecode, paquete, contenedor o binario. En un entorno corporativo deben documentarse la implementación, versión, runtime, dependencias y plataforma soportada.

8. JAVA Y LA PLATAFORMA JVM

8.1. Arquitectura general

Java fue diseñado como lenguaje de propósito general, orientado a objetos, con tipado estático y gestión automática de memoria. El compilador javac transforma archivos fuente en archivos de clase que contienen bytecode para la Java Virtual Machine. El launcher java inicia la JVM, carga clases y ejecuta el método de entrada. La JVM verifica bytecode, gestiona memoria y compila dinámicamente partes del programa.

FUENTE JAVA

├── javac
│ └── archivos .class con bytecode y metadatos

├── empaquetado
│ ├── JAR
│ └── módulos / dependencias

└── JVM
├── cargadores de clases
├── verificador
├── intérprete y JIT
├── garbage collector
└── bibliotecas nativas y sistema operativo

El lema «write once, run anywhere» expresa la portabilidad del bytecode, pero no garantiza que una aplicación sea independiente de todo entorno. El código puede depender de sistema de archivos, fuentes, zona horaria, codificaciones, bibliotecas nativas, permisos o comportamiento de la red. La portabilidad se consigue diseñando y probando para plataformas soportadas, no solo compilando a bytecode.

8.2. Lenguaje y tipos

Java diferencia tipos primitivos y referencias. Las clases definen estado y comportamiento; las interfaces expresan contratos; los genéricos permiten parametrizar tipos; las excepciones modelan fallos; y las anotaciones aportan metadatos. La herencia de clases es simple y se declara con extends; una clase puede implementar varias interfaces mediante implements. La composición suele preferirse a jerarquías profundas.

public final class Episodio {
    private final String identificador;

    public Episodio(String identificador) {
        this.identificador = identificador;
    }

    public String identificador() {
        return identificador;
    }
}
Perla real: en el examen TFA STI SAS 2021, turno libre, pregunta 119, se preguntó qué palabra clave se utiliza para crear en Java una subclase de otra ya existente. La respuesta fue extends. No debe confundirse con implements, reservado para la implementación de interfaces.

8.3. JVM, carga y ejecución

La JVM organiza memoria en áreas lógicas, crea hilos y ejecuta métodos. Los cargadores de clases siguen un modelo de delegación y permiten aislamiento. La verificación comprueba propiedades estructurales del bytecode. La compilación JIT utiliza perfiles para optimizar métodos frecuentes. El recolector de basura identifica objetos no alcanzables y recupera su memoria; existen distintos recolectores con objetivos de latencia, rendimiento o tamaño.

La recolección no gestiona automáticamente todos los recursos. Un flujo o conexión debe cerrarse, normalmente con try-with-resources. Las pausas, presión del heap y asignación excesiva se observan mediante métricas y perfiles. En servicios sanitarios con requisitos de disponibilidad, la configuración del runtime debe basarse en pruebas de carga y objetivos de latencia.

8.4. Plataforma y ecosistema

La plataforma Java incluye bibliotecas estándar para colecciones, concurrencia, E/S, red, criptografía, acceso a datos y muchas otras funciones. El ecosistema empresarial utiliza frameworks, servidores, contenedores y herramientas de construcción. Maven y Gradle gestionan dependencias y el ciclo de build. Los artefactos se publican en repositorios y se identifican por coordenadas y versiones.

javac SaludApp.java
java SaludApp

mvn test
./gradlew test

El ejemplo muestra comandos habituales. En proyectos reales, Maven o el wrapper de Gradle controlan el classpath, las pruebas y el empaquetado. El wrapper fija la versión de la herramienta y mejora la reproducibilidad.

8.5. Concurrencia y servicios

Java dispone de hilos, ejecutores, futuros, flujos y primitivas de sincronización. La evolución de la plataforma ha incorporado abstracciones para concurrencia de gran escala. Aun así, las garantías dependen del modelo de memoria: compartir estado mutable sin sincronización produce condiciones de carrera. En backend empresarial, es habitual combinar procesamiento síncrono, mensajería y APIs, con transacciones y observabilidad.

8.6. Versiones y soporte

Java publica versiones de características con cadencia regular y determinadas versiones reciben soporte prolongado. En agosto de 2026, Java 25 es la versión LTS más reciente y Java 26 es una versión de características vigente. En una organización no debe elegirse automáticamente la versión numéricamente mayor: se evalúan soporte, compatibilidad de frameworks, política de parches, licencia y horizonte de mantenimiento.

Estado del arte: la JVM combina verificación, JIT, recolección de basura, perfiles dinámicos y herramientas maduras. Junto al modo tradicional, existen compilación AOT e imágenes nativas para escenarios donde el arranque y el consumo son prioritarios.

8.7. Acceso a datos e interoperabilidad

JDBC define una API de acceso a bases de datos desde Java mediante drivers. No es un gestor de bases de datos ni un lenguaje de consulta; normalmente transporta SQL y mapea resultados. La interoperabilidad requiere gestionar pool de conexiones, transacciones, tipos, codificación y errores. Las capas ORM pueden reducir código repetitivo, pero no eliminan la necesidad de comprender SQL, índices y transacciones.

Perla real: en la OPE TFA STI SAS 2025, pregunta 151, se reconocieron ODBC y JDBC como interfaces que permiten conectar aplicaciones con distintos gestores relacionales de forma uniforme. JDBC se asocia al ecosistema Java; ODBC es una interfaz independiente del lenguaje con drivers específicos.

9. .NET, C# Y EL CLR

9.1. Plataforma unificada

.NET es una plataforma de desarrollo libre y multiplataforma que incluye runtime, bibliotecas, SDK, herramientas y lenguajes. La denominación moderna «.NET» continúa la línea iniciada por .NET Core; desde .NET 5 se abandonó «Core» en el nombre del producto unificado. .NET Framework permanece como tecnología histórica específica de Windows y no debe confundirse con las versiones actuales de .NET.

C# es el lenguaje más representativo, aunque el CLR admite otros lenguajes, como F# y Visual Basic. Los compiladores generan Common Intermediate Language —CIL— y metadatos. El ensamblado resultante puede ser una biblioteca o aplicación. En ejecución, el CLR carga los ensamblados, verifica y resuelve tipos, gestiona memoria y compila CIL a código nativo mediante JIT o, en determinados despliegues, utiliza código generado AOT.

CÓDIGO C# / F# / VB

├── compilador del lenguaje
│ ├── CIL
│ └── metadatos

├── ensamblado .NET
│ ├── manifiesto
│ ├── tipos y recursos
│ └── referencias

└── CLR
├── carga y resolución
├── JIT o AOT
├── garbage collector
├── excepciones e hilos
└── interoperabilidad nativa

9.2. CTS, CLS y metadatos

El Common Type System define cómo se declaran y usan los tipos en el runtime. El Common Language Specification establece un subconjunto de reglas para que componentes escritos en distintos lenguajes puedan interoperar. Los metadatos describen tipos, miembros, referencias y atributos, haciendo que los ensamblados sean auto-descriptivos. Esta arquitectura permite reflexión, herramientas de análisis y depuración cruzada.

9.3. C# como lenguaje

C# es estático, fuertemente tipado y multiparadigma. Incluye clases, interfaces, genéricos, delegados, eventos, expresiones lambda, consultas, pattern matching, tipos anulables y programación asíncrona. async y await expresan operaciones asíncronas sin convertir automáticamente el código en paralelo. Una tarea puede representar E/S pendiente y continuar en el mismo hilo lógico.

public sealed record Paciente(string Id, DateOnly FechaNacimiento);

public async Task<Paciente?> ObtenerAsync(string id, CancellationToken ct)
{
    return await repositorio.ObtenerAsync(id, ct);
}

El ejemplo usa un record inmutable para transportar datos y propaga un token de cancelación. La cancelación cooperativa es relevante en servicios: evita seguir consumiendo recursos cuando el cliente cancela o expira una solicitud.

9.4. Gestión de memoria y recursos

El CLR administra un heap recolectado y utiliza generaciones para optimizar objetos de vida corta. Los objetos no alcanzables pueden recuperarse, pero los recursos no administrados requieren liberación determinista mediante IDisposable y using. El finalizador es un mecanismo de respaldo costoso, no el patrón principal. La presión de memoria, grandes objetos y asignaciones deben medirse con herramientas de diagnóstico.

9.5. SDK, CLI y construcción

El SDK proporciona la CLI dotnet, compiladores y MSBuild. NuGet gestiona paquetes. Los proyectos describen objetivos, dependencias y propiedades. La construcción puede producir artefactos dependientes del framework, autocontenidos o nativos según el modelo de publicación.

dotnet new console -n SaludApp
dotnet build SaludApp
dotnet test
dotnet run --project SaludApp

9.6. Aplicaciones y servicios

.NET se utiliza en servicios web, aplicaciones de escritorio, cloud, procesos de datos y herramientas. ASP.NET Core proporciona infraestructura para APIs y aplicaciones web. Entity Framework Core ofrece mapeo objeto-relacional, aunque el diseño de consultas e índices sigue siendo responsabilidad técnica. La plataforma incluye mecanismos de configuración, inyección de dependencias, logging y métricas, pero cada proyecto debe definir políticas corporativas.

9.7. Versiones actuales

En agosto de 2026, .NET 10 es una versión LTS con soporte de tres años y C# 14 es su versión de lenguaje asociada estable. La política de versiones distingue lanzamientos LTS y de soporte estándar. La selección corporativa debe seguir una matriz aprobada y evitar runtimes fuera de soporte, porque dejan de recibir correcciones de seguridad.

Trampa: no es correcto afirmar que las aplicaciones .NET actuales solo se ejecutan en Windows. La plataforma moderna es multiplataforma. La restricción histórica se asocia principalmente a .NET Framework y a determinadas tecnologías ligadas a Windows.

9.8. JIT, ReadyToRun y Native AOT

El JIT compila métodos cuando se necesitan y puede optimizar con información de ejecución. ReadyToRun incluye código precompilado para reducir trabajo inicial, manteniendo capacidad de optimización adicional. Native AOT genera un ejecutable nativo y puede mejorar arranque y huella, pero impone restricciones a escenarios intensivos en reflexión o generación dinámica. La decisión debe basarse en el perfil de la aplicación, no en una preferencia universal.

10. PYTHON Y SU MODELO DE EJECUCIÓN

10.1. Lenguaje e implementaciones

Python es un lenguaje de alto nivel, multiparadigma, de tipado dinámico y con una sintaxis orientada a legibilidad. La implementación de referencia y más extendida es CPython, escrita principalmente en C. También existen PyPy, Jython, IronPython y otras implementaciones con objetivos distintos. Por ello, las características del lenguaje deben separarse de las particularidades de CPython, como su bytecode, su recolector o sus mecanismos internos.

10.2. Compilación a bytecode

CPython analiza el fuente, construye estructuras internas y lo compila a bytecode que ejecuta su máquina virtual. El bytecode puede almacenarse en archivos .pyc dentro de cachés para evitar recompilar módulos que no han cambiado. Es un formato interno y no una interfaz estable entre versiones. Llamar a Python «interpretado» es aceptable como clasificación práctica, pero afirmar que no existe compilación previa es incorrecto.

FUENTE PYTHON

├── parser y compilador de CPython
│ └── objeto de código / bytecode

├── caché opcional
│ └── archivos .pyc

└── runtime CPython
├── bucle de evaluación
├── objetos dinámicos
├── gestión de memoria
├── extensiones nativas
└── bibliotecas estándar y paquetes

10.3. Tipado dinámico y anotaciones

Las variables son nombres enlazados a objetos; el tipo pertenece al objeto, no al nombre. Esto facilita polimorfismo dinámico y duck typing. Los errores de tipo pueden aparecer al ejecutar un camino concreto. Las anotaciones permiten expresar tipos para herramientas estáticas, documentación e IDE, pero CPython no las aplica de forma general en runtime. El tipado gradual permite introducir rigor sin cambiar la semántica dinámica.

from dataclasses import dataclass

@dataclass(frozen=True)
class Cita:
    identificador: str
    prioridad: int

def es_prioritaria(cita: Cita) -> bool:
    return cita.prioridad >= 8

10.4. Modelo de objetos y memoria

En Python casi todo es un objeto: números, funciones, clases y módulos. CPython utiliza recuento de referencias combinado con un recolector para ciclos. Esto produce liberación frecuente al caer el contador, pero no debe usarse como garantía portable para recursos. Los context managers y la sentencia with gestionan de forma determinista archivos, bloqueos o transacciones.

10.5. Módulos, entornos y paquetes

Los módulos organizan código y los paquetes agrupan módulos. Los entornos virtuales aíslan dependencias por proyecto. pip instala distribuciones y pyproject.toml se ha convertido en pieza central para declarar sistemas de construcción y metadatos. En producción deben fijarse versiones, verificar hashes cuando proceda, usar repositorios controlados y revisar vulnerabilidades.

python -m venv .venv
python -m pip install --upgrade pip
python -m pytest

El entorno virtual no es un contenedor de seguridad; solo separa paquetes y ejecutables. Tampoco garantiza por sí mismo reproducibilidad si las versiones no están fijadas.

10.6. Concurrencia y paralelismo

Python ofrece threading, multiprocessing, asyncio y bibliotecas de alto nivel. En CPython tradicional, el GIL condiciona la ejecución paralela de bytecode en un proceso, aunque los hilos siguen siendo útiles para E/S y extensiones que liberan el bloqueo. Los procesos permiten paralelismo con memoria separada. La programación asíncrona utiliza un bucle de eventos y corrutinas cooperativas; no debe bloquearse con operaciones síncronas largas.

10.7. Ecosistema científico y automatización

Python destaca por su ecosistema de análisis de datos, aprendizaje automático, automatización, integración y APIs. Muchas bibliotecas de alto rendimiento delegan operaciones a código nativo y vectorizado; por ello, el rendimiento del programa no coincide con la velocidad del bucle interpretado. En salud, su uso puede incluir explotación de datos, validación, ETL, prototipado y modelos analíticos, siempre bajo controles de calidad, privacidad, explicabilidad y operación.

10.8. Estado de la versión

En agosto de 2026, la serie estable más reciente es Python 3.14; la versión 3.14.6 fue publicada en junio de 2026. La serie incorporó, entre otras novedades, binarios oficiales para nuevas plataformas y un JIT experimental en determinados binarios. Un entorno corporativo debe distinguir funciones experimentales de capacidades soportadas y mantener una política de actualización de parches.

Perla real: la OPE TFA STI SAS 2025 preguntó cuántas veces se ejecuta for i in [10]. La respuesta es una, porque la lista contiene un único elemento; el valor 10 no representa el número de iteraciones. Es una trampa sobre iterables, no sobre rangos.
for i in [10]:
    print(i)  # una iteración; i vale 10

for i in range(10):
    print(i)  # diez iteraciones; i toma valores de 0 a 9

10.9. Compilación y distribución

Una aplicación Python puede distribuirse como fuente, wheel, ejecutable empaquetado, contenedor o artefacto generado por compiladores especializados. Algunas herramientas embeben el intérprete; otras traducen o compilan partes a C o código nativo. Por eso hay que preguntar qué contiene realmente el artefacto y qué compatibilidad ofrece. «Generar un ejecutable» no implica necesariamente eliminar Python ni obtener el mismo comportamiento que un compilador de C.

11. LENGUAJES DE SCRIPTING

11.1. Concepto y evolución

Un script automatiza tareas dentro de un entorno anfitrión: shell, navegador, servidor, herramienta ofimática, motor de construcción o aplicación. Históricamente, los lenguajes de scripting se asociaron a interpretación, tipado dinámico y programas breves. Actualmente esas fronteras se han difuminado: JavaScript soporta aplicaciones complejas; Python se utiliza en servicios y ciencia; PowerShell trabaja con objetos y módulos; y PHP impulsa plataformas web de gran escala.

Las propiedades comunes son rapidez de desarrollo, acceso directo a APIs del host, composición de herramientas y facilidad para manipular texto o datos. Los riesgos son dependencia implícita del entorno, manejo débil de errores, secretos incrustados, falta de pruebas y crecimiento descontrolado. Cuando un script se convierte en pieza crítica debe recibir ingeniería de producto: repositorio, revisiones, pruebas, logging, gestión de versiones y despliegue controlado.

11.2. JavaScript y ECMAScript

JavaScript es una implementación del estándar ECMAScript y un lenguaje dinámico, basado en prototipos, con funciones de primera clase y modelo orientado a eventos. En navegador, el host aporta DOM, eventos, almacenamiento y APIs de red. En servidor, runtimes como Node.js proporcionan sistema de archivos, procesos, red y módulos. ECMAScript no define por sí solo todas las APIs del host.

Los motores modernos analizan y compilan dinámicamente. El bucle de eventos coordina tareas, microtareas y callbacks. La ejecución de JavaScript en un hilo principal no impide concurrencia del host; operaciones de E/S se completan fuera de la pila y notifican posteriormente. Las promesas y async/await estructuran flujos asíncronos, pero no convierten trabajo intensivo de CPU en no bloqueante.

async function cargarPaciente(id) {
  const respuesta = await fetch(`/api/pacientes/${id}`);
  if (!respuesta.ok) {
    throw new Error(`HTTP ${respuesta.status}`);
  }
  return respuesta.json();
}
Perla real: en el examen TFA STI SAS 2021, pregunta 72, JavaScript fue identificado como lenguaje de script. En las preguntas 74, 75 y 77 se evaluaron acceso a propiedades, igualdad estricta y el objeto XMLHttpRequest, lo que confirma que el examen puede descender a semántica concreta del lenguaje y APIs web.

11.3. TypeScript

TypeScript amplía JavaScript con un sistema de tipos estático y se transpila a JavaScript. Los tipos se eliminan en la salida: no validan automáticamente datos recibidos por red. Por ello, una API debe comprobar esquemas en runtime aunque el cliente esté tipado. TypeScript mejora refactorización, navegación y detección temprana, pero no modifica el modelo de ejecución del motor JavaScript.

11.4. Shell y Bash

Las shells interpretan comandos y proporcionan variables, expansiones, redirecciones, tuberías, sustitución y control de procesos. Bash es común en Unix y Linux. Su fortaleza es componer utilidades; su debilidad aparece al manejar datos estructurados, errores sutiles, espacios, codificaciones o portabilidad. Deben citarse variables, comprobar códigos de salida y evitar analizar texto frágil cuando existe una interfaz estructurada.

set -euo pipefail

origen="/srv/datos"
destino="/srv/copias"
tar -czf "$destino/copia.tgz" -C "$origen" .

El modo estricto reduce algunos fallos, pero no sustituye pruebas. Un script con privilegios debe validar rutas y entradas para evitar inyección de comandos o borrados accidentales.

11.5. PowerShell

PowerShell es una shell y lenguaje de automatización orientado a objetos. Sus tuberías transportan objetos .NET en lugar de limitarse a texto. Los cmdlets siguen convenciones de nombres y parámetros. Es especialmente útil en administración Windows, Microsoft 365 y entornos híbridos, aunque también es multiplataforma. La política de ejecución no debe interpretarse como frontera de seguridad completa; la firma, el control de acceso y el origen de los scripts siguen siendo necesarios.

11.6. PHP

PHP es un lenguaje de propósito general especialmente extendido en desarrollo web del lado servidor. El servidor o runtime ejecuta el código y produce la respuesta, a menudo HTML o JSON. Sus versiones modernas incluyen tipos, clases, excepciones y herramientas de dependencias. La seguridad depende de parametrizar consultas, escapar según contexto, validar entradas, gestionar sesiones y mantener frameworks y extensiones actualizados.

Perla real: en el examen TFA STI SAS 2021, pregunta 47, se preguntó en qué lenguaje había librerías y módulos publicados de MADEJA; la respuesta fue PHP. Debe memorizarse como dato histórico del marco y del examen, sin convertirlo en una afirmación sobre la pila corporativa vigente en 2026.

11.7. Otros lenguajes y configuración

Ruby, Perl, Lua y Tcl mantienen nichos importantes. Además, muchos ficheros de automatización utilizan YAML, JSON o TOML, que son formatos de datos, no lenguajes de programación generales. Algunos sistemas añaden expresiones o plantillas sobre esos formatos. Confundir configuración declarativa con código ejecutable puede ocultar riesgos: plantillas y pipelines pueden ejecutar acciones con privilegios.

Seguridad: nunca deben incorporarse credenciales al repositorio ni construirse comandos concatenando entradas no confiables. Los scripts de operación deben usar gestores de secretos, mínimos privilegios, registros y revisiones como cualquier otro software.

12. ENTORNOS VISUALES E IDE

12.1. Editor, IDE y entorno visual

Un editor de código ofrece edición, resaltado y extensiones. Un IDE integra edición, compilación o ejecución, depuración, navegación semántica, pruebas, refactorización y control de versiones. Un entorno visual añade diseñadores gráficos, paletas de componentes, propiedades y generación de código. Las fronteras se difuminan: un editor extensible puede aproximarse a un IDE y un IDE puede ejecutar herramientas externas.

La ventaja principal de la integración es que todas las operaciones comparten un modelo del proyecto. El IDE puede resolver símbolos, anticipar errores, ejecutar una prueba concreta y detenerse en una excepción. El riesgo es depender de configuraciones ocultas que no se reproducen fuera del equipo. El build debe poder ejecutarse en línea de comandos y en integración continua.

12.2. Funciones esenciales

Función Finalidad Riesgo si se usa mal
Autocompletado Proponer símbolos según contexto Aceptar APIs sin comprenderlas
Refactorización Cambiar estructura preservando comportamiento Confiar sin ejecutar pruebas
Depurador Inspeccionar ejecución, pila y variables Modificar estado y alterar el defecto
Análisis estático Detectar defectos sin ejecutar Ignorar falsos positivos sin criterio
Diseñador visual Construir interfaces y componentes Generar código opaco o acoplado
Integración VCS Comparar, confirmar y revisar cambios Operaciones masivas accidentales

12.3. IDE representativos

Visual Studio proporciona una experiencia completa para .NET, C++ y otros escenarios. IntelliJ IDEA se especializa en JVM y dispone de análisis profundo. Eclipse mantiene una arquitectura de plugins y un amplio uso. PyCharm se orienta a Python. Visual Studio Code es un editor extensible basado en un núcleo abierto, mientras que la distribución oficial de Microsoft incorpora componentes y condiciones propias; por tanto, decir sin matiz que «VS Code es enteramente open source» puede ser impreciso.

Perla real: el examen TFA STI SAS 2021, pregunta 52, pidió identificar qué entorno de desarrollo no tenía su código fuente publicado como código abierto; la respuesta fue Sublime Text. El distractor habitual consiste en asumir que todo editor multiplataforma y ampliable es software libre.

12.4. Protocolo de servidor de lenguaje

El Language Server Protocol separa la interfaz del editor de un servidor que conoce el lenguaje. Así, navegación, diagnósticos, referencias y completado pueden reutilizarse entre editores. El servidor mantiene un modelo incremental del proyecto. Esta arquitectura reduce duplicación, aunque la calidad depende de cada implementación y del sistema de construcción.

12.5. Diseñadores RAD y generación de código

Los entornos RAD permiten arrastrar componentes, definir eventos y generar formularios. Aceleran aplicaciones de datos y prototipos, pero pueden mezclar presentación, lógica y acceso a datos. El código generado debe considerarse artefacto: hay que saber si puede editarse, regenerarse y versionarse. En proyectos duraderos, la arquitectura debe evitar quedar cautiva de un diseñador sin soporte.

12.6. Desarrollo remoto y contenedores

Los IDE actuales pueden conectarse a servidores, WSL, máquinas virtuales o contenedores. Un contenedor de desarrollo define herramientas y dependencias, reduciendo diferencias entre equipos. No sustituye la seguridad del puesto ni el control del repositorio. Las extensiones del IDE ejecutan código con acceso al proyecto, por lo que deben administrarse y actualizarse como componentes de la cadena de suministro.

12.7. Depuración

El depurador usa símbolos para relacionar instrucciones con fuente. Permite breakpoints, ejecución paso a paso, evaluación de expresiones, inspección de hilos y volcados. En producción suele preferirse observabilidad y depuración post mortem para no detener servicios. Un breakpoint puede cambiar temporización y ocultar carreras; este fenómeno obliga a complementar con trazas y herramientas de concurrencia.

13. HERRAMIENTAS DE CONSTRUCCIÓN, DEPENDENCIAS, PRUEBAS Y CI/CD

13.1. Construcción reproducible

La construcción transforma fuente y recursos en artefactos desplegables. Incluye compilación, generación, pruebas, análisis, empaquetado y publicación. Debe estar automatizada y ser reproducible: el mismo código y entradas controladas deben producir resultados equivalentes. Las dependencias implícitas del equipo del desarrollador son una fuente clásica de fallos.

Maven y Gradle dominan gran parte del ecosistema Java; MSBuild y la CLI dotnet estructuran .NET; Python utiliza sistemas definidos mediante pyproject.toml; npm y herramientas asociadas gestionan JavaScript. La herramienta no sustituye un diseño correcto del grafo. Los scripts de build forman parte del software y requieren revisión.

13.2. Gestión de dependencias

Un gestor resuelve paquetes y versiones, descarga artefactos y construye un grafo transitivo. Los rangos flexibles facilitan actualizaciones, pero pueden romper reproducibilidad. Los lockfiles fijan resoluciones concretas. En Java, las coordenadas identifican grupo, artefacto y versión; en .NET, NuGet gestiona paquetes; en Python, se combinan requisitos y herramientas de bloqueo; en JavaScript, npm mantiene un árbol y lockfile.

La dependencia transitiva es código que la aplicación ejecuta aunque el equipo no la haya elegido directamente. Debe inventariarse, actualizarse y analizarse. El riesgo incluye vulnerabilidades, typosquatting, paquetes comprometidos, scripts de instalación y licencias incompatibles.

13.3. Pruebas

Las pruebas unitarias verifican unidades aisladas; las de integración comprueban interacción entre componentes; las de contrato validan APIs; las end-to-end recorren flujos; y las de rendimiento miden bajo carga. La pirámide es una heurística, no una ley. Las pruebas deben ser deterministas, rápidas en su nivel y capaces de fallar por la causa correcta.

mvn test
dotnet test
python -m pytest
npm test

Un pipeline debe ejecutar además análisis estático, escaneo de dependencias y construcción del artefacto. Las pruebas que requieren bases de datos o servicios deben usar entornos controlados, datos sintéticos y limpieza.

13.4. Integración y entrega continuas

La integración continua compila y valida cada cambio con frecuencia. La entrega continua mantiene el software en estado desplegable; el despliegue continuo publica automáticamente cuando se superan controles. Los términos no son idénticos. En sistemas sanitarios puede existir aprobación humana y ventanas de cambio, por lo que el pipeline automatiza evidencia y promoción sin eliminar gobernanza.

COMMIT

├── validación rápida
│ ├── formato y lint
│ ├── compilación
│ └── pruebas unitarias

├── validación profunda
│ ├── integración y contratos
│ ├── SAST y dependencias
│ └── rendimiento selectivo

├── artefacto inmutable
│ ├── firma / hash
│ ├── SBOM
│ └── repositorio

└── promoción
├── pruebas de entorno
├── aprobación según riesgo
└── despliegue y observabilidad

13.5. Análisis y calidad

Los linters detectan convenciones y patrones; los analizadores estáticos construyen modelos de flujo; los formateadores reducen discusiones; y las métricas ayudan a localizar complejidad. Ninguna métrica debe convertirse en objetivo aislado. Cobertura alta no demuestra calidad si las aserciones son débiles. La revisión humana sigue siendo necesaria para arquitectura, seguridad, privacidad y adecuación funcional.

13.6. Depuración y perfilado

El perfilado mide CPU, memoria, asignaciones, I/O, bloqueos y latencia. Un profiler de muestreo tiene menor intrusión que uno instrumentado. Las optimizaciones deben dirigirse a cuellos de botella medidos. En servicios, las trazas distribuidas, métricas y logs correlacionados permiten seguir una petición. Los datos de observabilidad no deben exponer información clínica o identificadores innecesarios.

13.7. Seguridad de la cadena de suministro

La cadena comprende IDE, extensiones, compiladores, runners, repositorios, paquetes, imágenes y credenciales. Las medidas incluyen mínimos privilegios, runners efímeros, revisión de acciones, fijación de versiones, firma de artefactos, SBOM y segregación de entornos. Un pipeline comprometido puede insertar código aunque el repositorio esté protegido.

Criterio corporativo: el artefacto que se despliega debe ser el mismo que se probó. Reconstruir manualmente en producción rompe trazabilidad y puede introducir dependencias diferentes.

14. ESTADO DEL ARTE DE TÉCNICAS Y ENTORNOS DE DESARROLLO

14.1. Desarrollo políglota y arquitecturas distribuidas

Las organizaciones utilizan varios lenguajes porque ningún ecosistema optimiza todos los dominios. Java o .NET pueden sostener servicios transaccionales; Python, procesos analíticos; JavaScript o TypeScript, interfaces; y shells, automatización. El enfoque políglota es útil cuando cada elección tiene una razón, pero aumenta formación, observabilidad, parcheo y complejidad operativa. La estandarización debe limitar combinaciones sin prohibir excepciones justificadas.

14.2. Contenedores, cloud y plataformas internas

Los contenedores empaquetan aplicación y dependencias de espacio de usuario, pero comparten el kernel. Facilitan despliegues consistentes y escalado, no convierten automáticamente una aplicación en cloud-native. Las plataformas internas para desarrolladores ofrecen plantillas, pipelines, entornos, secretos y observabilidad como autoservicio gobernado. Su objetivo es reducir carga cognitiva y variabilidad, no ocultar completamente la infraestructura.

14.3. Microservicios y modularidad

Los microservicios permiten despliegue independiente y escalado selectivo, pero introducen red, consistencia distribuida, descubrimiento, contratos, telemetría y operación. Un monolito modular puede ser preferible cuando el dominio y el equipo no justifican distribución. La elección de lenguaje por servicio debe equilibrar autonomía con capacidad de soporte. En salud, la consistencia de datos y la continuidad asistencial exigen especial cautela.

14.4. WebAssembly

WebAssembly define un formato binario portable y una máquina abstracta diseñada para ejecución eficiente y segura dentro de hosts. Surgió en navegador y se extiende a servidor y plugins mediante interfaces de sistema. Puede ser destino de varios lenguajes y facilita sandboxing, pero no reemplaza JavaScript ni ofrece por sí solo acceso al entorno. Las APIs del host y el modelo de componentes determinan la integración.

14.5. AOT, imágenes nativas y arranque

La presión de serverless, microservicios y edge impulsa compilación AOT e imágenes nativas. Java y .NET ofrecen opciones para reducir arranque y memoria. El coste es restringir reflexión y generación dinámica, aumentar complejidad del build y, en ocasiones, perder optimización adaptativa. La decisión debe medir tiempo de arranque, consumo sostenido, latencia y esfuerzo de mantenimiento.

14.6. Python con JIT experimental y especialización

Las implementaciones de Python exploran especialización adaptativa, JIT y ejecución sin determinadas restricciones históricas. En la serie 3.14 existe un JIT experimental en algunos binarios oficiales. «Experimental» significa que no debe asumirse estabilidad, rendimiento universal ni adecuación automática a producción. Los avances muestran que la frontera intérprete-compilador continúa difuminándose.

14.7. JavaScript contemporáneo

ECMAScript evoluciona anualmente y en 2026 dispone de una especificación vigente. Los motores aplican parsing, bytecode, JIT y recolectores sofisticados. Node.js mantiene líneas Current y LTS; en agosto de 2026, Node.js 24 es LTS y Node.js 26 es Current. Para producción se prefiere normalmente una línea LTS compatible con dependencias y política corporativa.

14.8. Inteligencia artificial asistiendo al desarrollo

Los asistentes de IA generan código, pruebas, documentación y explicaciones. Aumentan velocidad en tareas repetitivas, pero pueden producir APIs inexistentes, vulnerabilidades, licencias dudosas o lógica incorrecta. Deben operar bajo revisión, pruebas, análisis y políticas de datos. No se debe enviar código o información sensible a servicios no autorizados. La responsabilidad del cambio continúa siendo humana y organizativa.

Trampa actual: «generado por IA» no equivale a «verificado». La plausibilidad sintáctica puede ocultar errores semánticos, dependencias inexistentes o vulnerabilidades. El criterio de aceptación debe ser el mismo o más exigente que para código escrito manualmente.

14.9. Low-code y no-code

Las plataformas low-code permiten modelar datos, procesos e interfaces con componentes visuales y generación. Son adecuadas para flujos estandarizados y prototipos, pero deben evaluarse extensibilidad, rendimiento, seguridad, exportación, pruebas, gobierno y dependencia del proveedor. «No-code» describe la experiencia del usuario, no la ausencia de software: la plataforma contiene código, runtimes y configuraciones complejas.

14.10. Desarrollo seguro por diseño

El estado del arte integra seguridad desde requisitos: modelado de amenazas, análisis estático, composición de software, pruebas, secretos y hardening. La memoria segura gana importancia en software de sistemas; los runtimes gestionados reducen clases de errores, pero no evitan inyección, autorización defectuosa o exposición de datos. La seguridad debe abarcar lenguaje, framework, configuración y operación.

14.11. Reproducibilidad y procedencia

Las prácticas modernas registran procedencia del artefacto, dependencias y entorno de construcción. SBOM, firmas y attestations permiten saber qué se desplegó y cómo se generó. Estas técnicas facilitan respuesta a vulnerabilidades: localizar qué sistemas incluyen un componente y reconstruir de forma controlada.

14.12. Observabilidad como requisito de desarrollo

Logs estructurados, métricas y trazas se diseñan junto con el código. La telemetría debe incluir correlación y contexto técnico, pero minimizar datos personales. En un entorno sanitario, registrar contenido clínico por defecto puede vulnerar confidencialidad. La observabilidad eficaz separa identificadores técnicos, aplica controles de acceso y define retención.

15. SELECCIÓN TECNOLÓGICA Y APLICACIÓN EN EL SAS

15.1. Decisión multicriterio

Elegir un lenguaje para una aplicación del SAS exige evaluar funcionalidad, arquitectura, rendimiento, seguridad, interoperabilidad, soporte, competencias, coste total y vida útil. El criterio no es «qué lenguaje es mejor», sino qué combinación reduce riesgo y satisface requisitos. La decisión debe documentarse mediante una arquitectura o ADR con alternativas y consecuencias.

Criterio Preguntas Evidencia
Alineamiento corporativo ¿Está aprobado el stack y existe soporte? Catálogo tecnológico y arquitectura
Mantenibilidad ¿Hay equipo, pruebas y documentación? Capacidad interna y métricas
Seguridad ¿Recibe parches y dispone de análisis? Ciclo de soporte y evaluación
Interoperabilidad ¿Implementa APIs y estándares requeridos? Contratos, pruebas y perfiles
Rendimiento ¿Cumple latencia, carga y consumo? Pruebas representativas
Operación ¿Se observa, despliega y recupera? Runbooks, SLO y automatización
Coste total ¿Qué supone durante todo el ciclo? Licencias, infraestructura y personal

15.2. Alineamiento con la Junta de Andalucía

La Junta mantiene un portal de Desarrollo de Servicios Digitales y normas de alineamiento con la pila tecnológica. Estas referencias evolucionan; por ello, un temario no debe convertir una versión puntual de producto en verdad permanente. En junio de 2026 se actualizó la relación de tecnologías, productos y estándares aprobados. En un proyecto real debe consultarse la versión vigente y solicitar excepción cuando exista una necesidad justificada.

MADEJA aparece en exámenes y documentación histórica como marco metodológico y tecnológico. El opositor debe conocer el dato preguntado, pero también distinguir entre contenido histórico y políticas actuales. Las plataformas corporativas, estándares de seguridad, administración electrónica e interoperabilidad condicionan la solución más que una preferencia por Java, .NET o Python.

15.3. Integración sanitaria

Los sistemas sanitarios intercambian información mediante APIs, mensajería, documentos y estándares clínicos. El lenguaje es secundario frente al cumplimiento exacto de contratos, perfiles y terminologías. Java, .NET, Python y Node.js pueden implementar REST o procesar JSON; eso no garantiza interoperabilidad semántica. Deben validarse esquemas, identificadores, codificación, versionado y comportamiento ante errores.

15.4. Seguridad y protección de datos

El software debe cumplir el Esquema Nacional de Seguridad, la protección de datos y las políticas corporativas. Se aplican mínimos privilegios, autenticación y autorización centralizadas, cifrado, trazabilidad, segregación y gestión de vulnerabilidades. Los logs no deben contener información clínica salvo necesidad y control. Las dependencias han de mantenerse y los runtimes fuera de soporte deben retirarse.

15.5. Casos de uso razonables

Java es adecuado para servicios empresariales con ecosistema JVM, portabilidad y operación madura. .NET resulta natural cuando existe plataforma Microsoft, equipos C# y servicios multiplataforma. Python destaca en automatización, datos, integración y analítica, pero una prueba de concepto debe industrializarse antes de convertirse en servicio crítico. TypeScript favorece interfaces mantenibles y servicios JavaScript. Bash o PowerShell son apropiados para automatización operativa limitada y controlada.

Caso: un proceso de validación de ficheros puede prototiparse en Python por su capacidad de manipulación. Si pasa a ejecutar cargas críticas, necesitará empaquetado, pruebas de regresión, límites de recursos, observabilidad, gestión de dependencias y soporte. El lenguaje no cambia; cambia la ingeniería aplicada.

15.6. Evitar la proliferación tecnológica

Cada nuevo lenguaje añade compiladores, imágenes, repositorios, reglas de seguridad, formación y guardias. La autonomía de equipos debe equilibrarse con una plataforma común. Un lenguaje minoritario puede justificarse por una ventaja decisiva, pero requiere propietario, plan de soporte, monitorización y estrategia de salida.

15.7. Accesibilidad y calidad de interfaces

Los entornos visuales facilitan construir pantallas, pero no garantizan accesibilidad. La salida debe cumplir criterios de percepción, operación, comprensión y robustez. Los componentes generados deben probarse con teclado y tecnologías asistivas. La calidad visual no puede ocultar errores de foco, etiquetas o contraste.

15.8. Contratación y transferencia

Cuando el desarrollo se contrata, deben definirse entrega de código, documentación, pipelines, dependencias, pruebas, propiedad y transferencia. Un ejecutable sin fuentes ni procedimiento reproducible crea cautividad. Los criterios de aceptación deben incluir seguridad, rendimiento, mantenibilidad y capacidad de desplegar en entornos corporativos.

Regla de selección: tecnología soportada, equipo competente, artefacto reproducible, dependencias gobernadas y operación observable. El rendimiento teórico de un lenguaje es irrelevante si el sistema no puede mantenerse o parchearse.

16. COMPARATIVA GLOBAL E IDEAS DE REPASO

16.1. Comparación de plataformas

Aspecto Java .NET / C# Python JavaScript / TypeScript
Tipado principal Estático Estático Dinámico con anotaciones opcionales Dinámico; TypeScript añade tipado estático borrado
Representación Bytecode JVM CIL y metadatos Bytecode interno en CPython Representaciones internas del motor
Runtime JVM CLR CPython u otra implementación Navegador, Node.js u otro host
Optimización JIT y opciones AOT JIT y Native AOT Interpretación especializada; JIT según implementación JIT en motores modernos
Fortalezas Backend empresarial y ecosistema Productividad, tooling y servicios Datos, automatización y rapidez Web, eventos y full-stack
Riesgo típico Complejidad de plataforma Confundir .NET con Framework Dependencias y dinamismo sin controles Ecosistema cambiante y asincronía

16.2. Distinciones que debes dominar

  • Fuente / objeto / ejecutable: representan etapas diferentes.
  • Bytecode / máquina: el primero apunta a una VM; el segundo a una ISA.
  • Compilador / intérprete: son estrategias combinables, no etiquetas absolutas.
  • JIT / AOT: durante la ejecución frente a antes del despliegue.
  • API / ABI: contrato de fuente frente a contrato binario.
  • Lenguaje / implementación: Python no es sinónimo de CPython; Java no es una JVM concreta.
  • IDE / editor: la integración semántica y de herramientas marca la diferencia.
  • Script / programa: el uso y el host importan más que el tamaño.
  • Garbage collector / cierre de recursos: memoria automática no libera por sí sola todos los recursos externos.
  • Tipado estático / compilación: son dimensiones independientes.

16.3. Errores frecuentes

Es incorrecto afirmar que el compilador siempre produce código máquina, que el intérprete siempre ejecuta línea por línea, que Python no compila, que Java es independiente de cualquier entorno o que .NET solo funciona en Windows. También es incorrecto suponer que ensamblador manual siempre supera al compilador, que un entorno visual garantiza calidad o que una plataforma low-code elimina la necesidad de gobierno.

Orientación de examen: las preguntas reales han combinado definiciones —bytecode, lenguaje de script— con sintaxis concreta —extends, bucles Python, igualdad JavaScript— y conocimiento de herramientas —Sublime Text, MADEJA, JDBC—. Conviene estudiar conceptos y pequeños ejemplos ejecutables.

16.4. Conclusión

El estado del arte no elimina los fundamentos; los refuerza. Las máquinas virtuales, JIT, AOT, WebAssembly y asistentes de IA siguen apoyándose en análisis léxico, sintáctico y semántico, representaciones intermedias, tipos y modelos de memoria. La competencia profesional consiste en comprender esa cadena, seleccionar la tecnología adecuada y construir un proceso reproducible, seguro y mantenible.

17. MAPA CONCEPTUAL

LENGUAJES DE PROGRAMACIÓN

├── FUNDAMENTOS
│ ├── sintaxis · semántica · pragmática
│ ├── tipos · ámbito · enlace · memoria
│ └── paradigmas · modularidad · concurrencia

├── TRADUCCIÓN
│ ├── preprocesador
│ ├── compilador: tokens → AST → semántica → IR → código
│ ├── ensamblador: mnemónicos → objeto
│ ├── enlazador y cargador
│ └── intérprete / VM / JIT / AOT

├── PLATAFORMAS
│ ├── Java → javac → bytecode → JVM
│ ├── C# → CIL + metadatos → CLR
│ ├── Python → bytecode CPython → runtime
│ └── JavaScript → motor del host · TypeScript → JavaScript

├── ENTORNOS
│ ├── IDE · depurador · servidor de lenguaje
│ ├── build · paquetes · pruebas
│ ├── CI/CD · análisis · observabilidad
│ └── contenedores · plataforma interna

├── TENDENCIAS
│ ├── AOT e imágenes nativas
│ ├── WebAssembly
│ ├── low-code
│ ├── IA asistiendo al desarrollo
│ └── seguridad de cadena de suministro

└── SELECCIÓN EN EL SAS
├── alineamiento corporativo
├── seguridad y protección de datos
├── interoperabilidad y accesibilidad
├── soporte y competencias
└── mantenibilidad, coste y operación

18. REFERENCIAS NORMATIVAS Y BIBLIOGRÁFICAS

  • Temario oficial TFA Sistemas y Tecnología de la Información del SAS — enunciado oficial del Tema 46.
  • Oracle, Java Language Specification y Java Virtual Machine Specification — definición del lenguaje Java y de la JVM.
  • Oracle, Java SE Support Roadmap — cadencia y versiones LTS de Java.
  • Microsoft Learn, Managed Execution Process y CLR overview — CIL, metadatos, JIT y servicios del runtime.
  • Microsoft, .NET Support Policy y documentación de .NET 10 / C# 14 — ciclo de soporte y características de la plataforma.
  • Python Language Reference y Python 3.14 documentation — modelo de ejecución, bytecode y semántica del lenguaje.
  • Python Software Foundation, Python 3.14.6 release — versión estable de referencia en junio de 2026.
  • ECMA-262, ECMAScript 2026 Language Specification — especificación normativa de ECMAScript.
  • Node.js Release Schedule — líneas Current y LTS.
  • Aho, Lam, Sethi y Ullman, Compilers: Principles, Techniques, and Tools — fundamentos de compiladores.
  • Cooper y Torczon, Engineering a Compiler — análisis, IR, optimización y generación.
  • Junta de Andalucía, Portal de Desarrollo de Servicios Digitales — normas, pila tecnológica e iniciativas corporativas.
  • Normas para el Desarrollo de Servicios Web de la Junta de Andalucía — criterios de APIs, HTTP e intercambio de información.
  • Real Decreto 311/2022, Esquema Nacional de Seguridad — requisitos de seguridad aplicables al desarrollo y operación.
  • Real Decreto 4/2010, Esquema Nacional de Interoperabilidad — interoperabilidad organizativa, semántica y técnica.
  • Reglamento (UE) 2016/679 y Ley Orgánica 3/2018 — protección de datos personales y garantía de derechos digitales.
  • Exámenes TFA STI SAS 2019, 2021 y 2025 — preguntas reales no anuladas sobre bytecode, Python, Java, JavaScript, entornos y JDBC.
lenguajes de programación
compilador
intérprete
ensamblador
bytecode
JIT y AOT
Java JVM
.NET CLR
Python
JavaScript scripting
IDE
TFA STI SAS

Pon a prueba lo aprendido

Banco con 32 preguntas sobre este tema. Genera un quiz aleatorio cuando quieras.

Test completo →