Saltar a contenido

UD 1 - P15: Solución orientativa de clasificación de lenguajes

Solución orientativa de la práctica P15

Esta solución ofrece ejemplos para contrastar el trabajo, no una única redacción válida. Los resultados y comandos concretos pueden variar según el sistema operativo, la versión de las herramientas y el entorno elegido. La clasificación debe indicar siempre qué implementación se está considerando y evitar presentar categorías complementarias como si fueran excluyentes.

Ejercicio 1: ejecución de la suma

Pregunta 1.a: Documenta la comparación de los dos lenguajes de tu itinerario.

Subpregunta 1.a.1: Incluye los comandos y las versiones utilizados.

Respuesta orientativa: Registra los comandos exactos que se ejecutaron. Las versiones pueden consultarse con gcc --version, python --version, javac --version, java --version o node --version, según el itinerario. Si se utilizó un navegador, anota el nombre y la versión que muestra su apartado de información.

Subpregunta 1.a.2: ¿Qué salida esperabas y cuál obtuviste?

Respuesta orientativa: El cálculo es 5 + 7, por tanto todos los programas deben producir una salida equivalente a:

El resultado es: 12

En JavaScript, el navegador o Node.js pueden mostrar el texto y el número con un espacio entre ambos; la presentación exacta depende de la consola. Lo importante es que el valor calculado sea 12.

Subpregunta 1.a.3: ¿Qué herramientas o entornos intervinieron antes y durante la ejecución?

Respuesta orientativa: La herramienta usada depende del itinerario y del sistema elegido. La tabla muestra un proceso habitual para cada lenguaje; pueden aceptarse otros comandos equivalentes si se indica qué herramienta se utilizó.

Lenguaje Herramienta o entorno de ejemplo Proceso habitual observado
C GCC gcc suma.c -o suma genera un ejecutable nativo para una plataforma; después se ejecuta el archivo generado.
Python CPython python suma.py inicia el intérprete. CPython suele compilar el fuente a bytecode, que procesa su máquina virtual; el bytecode puede almacenarse en caché.
Java javac y JVM javac Suma.java genera bytecode en Suma.class; java Suma inicia una JVM compatible, que puede interpretar o compilar partes con JIT.
JavaScript Navegador o Node.js El motor analiza y ejecuta el código; los motores modernos pueden interpretar y optimizar partes con JIT. El detalle depende del motor.

No es preciso afirmar que C siempre es compilado o que Python y JavaScript nunca se compilan. Estas descripciones resumen implementaciones habituales. Java tampoco genera directamente un ejecutable nativo con la orden javac: genera bytecode para la JVM.

Subpregunta 1.a.4: ¿En qué momento se detectarían los errores sintácticos que probaste? Distingue un error sintáctico de uno que aparezca durante la ejecución.

Respuesta orientativa:

Un compilador como GCC o javac informa de errores de sintaxis durante la compilación y no genera una salida válida para esa versión del programa. En Python y JavaScript, el analizador normalmente detecta errores sintácticos al analizar el programa o el fragmento antes de ejecutar sus instrucciones; en un entorno interactivo puede analizarse cada fragmento por separado. Los errores de ejecución —por ejemplo, una operación inválida con ciertos datos— son diferentes y pueden ocurrir después de iniciar el programa. Por ello, no debe generalizarse que el intérprete detecta errores de sintaxis «línea por línea» solo cuando llega a una línea.

Ejercicio 2: alto nivel y bajo nivel

Enunciado 2.a: Adjunta la tabla comparativa de Python o Java, C y ensamblador.

Subpregunta 2.a.1: Explica por qué «C es de bajo nivel» es una descripción relativa e incompleta.

Respuesta orientativa: Una comparación válida sería:

Aspecto Python o Java C Ensamblador del ejemplo
Nivel de abstracción relativo Alto: permite expresar operaciones sin nombrar directamente registros físicos. Menos abstracto y más próximo al sistema que Python o Java en distintos aspectos, aunque dispone de tipos, funciones y estructuras de alto nivel. Muy bajo y ligado a una arquitectura: el ejemplo nombra registros e instrucciones.
Operación num1 + num2 expresa la suma con variables. También expresa la operación mediante variables y +. MOV carga o copia valores y ADD realiza la suma en un registro.
Detalles de máquina visibles La gestión de registros y las instrucciones concretas quedan ocultas al código de aplicación. Permite más control sobre memoria y representación, pero no asigna necesariamente cada variable a un registro concreto en el fuente. Son visibles AX, BX y el orden de las operaciones.
Portabilidad y ejecución Requiere el intérprete, la JVM o un motor compatible, según el caso. El ejecutable suele depender del sistema y la arquitectura de destino; es posible compilar para distintos destinos. Depende de la arquitectura y del ensamblador; las instrucciones del fragmento no valen para cualquier procesador.

El fragmento MOV AX, 5 / ADD AX, 7 / MOV BX, AX deja el resultado 12 en AX y después copia ese valor en BX. No incluye una rutina de entrada/salida ni constituye por sí solo un programa ejecutable completo. La sintaxis y la disponibilidad de los registros dependen del ensamblador y de la arquitectura x86 escogida.

La frase «C es de bajo nivel» es una descripción relativa: C permite operaciones y control próximos al sistema, incluida gestión explícita de memoria, pero ofrece abstracciones que no aparecen en el ensamblador. Se puede afirmar que suele estar más cerca del sistema que Java o Python, pero no equipararlo a instrucciones de ensamblador.

Ventajas y limitaciones posibles:

  • Alto nivel: facilita la lectura, el desarrollo rápido y el mantenimiento; a cambio, abstrae detalles y depende de un entorno de ejecución o bibliotecas según el lenguaje.
  • C: ofrece control, rendimiento y acceso amplio a las interfaces del sistema; exige más atención a memoria, seguridad y portabilidad que entornos con gestión automática.
  • Ensamblador: permite controlar instrucciones y registros de una arquitectura concreta; requiere más trabajo y conocimiento de plataforma, y el código suele ser menos portable.

No se deduce de estas características que un lenguaje de menor nivel sea siempre más rápido: el compilador, el algoritmo, las bibliotecas, las restricciones y las medidas del programa también importan.

Ejercicio 3: paradigmas y estilos

Enunciado 3.a: Compara el objeto Coche y la función pura suma.

Subpregunta 3.a.1: Identifica dónde se conserva el estado en el ejemplo orientado a objetos.

Respuesta orientativa:

En la implementación Java, la salida esperada es:

Velocidad: 10

Coche es una clase; miCoche es un objeto; marca y velocidad son atributos; acelerar() es un método que cambia el estado de la instancia aumentando la velocidad en 10. La clase describe una estructura común y el objeto conserva valores concretos.

Subpregunta 3.a.2: Explica qué cambia al calcular el resultado mediante una función que devuelve un valor.

Respuesta orientativa:

En Python, suma(5, 7) devuelve 12. La función no cambia una variable global ni modifica los argumentos; para las mismas entradas devuelve el mismo resultado. En este ejemplo es pura. Sin embargo, definir una función pura no significa que todo el programa sea funcional ni que Python pertenezca exclusivamente a ese paradigma: Python admite estilos imperativos, orientados a objetos y funcionales.

La orientación a objetos organiza datos y comportamiento alrededor de objetos con estado. El ejemplo funcional presenta una transformación de entradas a una salida, sin modificar estado externo. Ambos enfoques pueden combinarse en lenguajes multiparadigma.

Ejercicio 4: tabla de clasificación

Enunciado 4.a: Completa la tabla solicitada en el paso 4.5 y recomienda un lenguaje para uno de los escenarios. Incluye las limitaciones de tu recomendación.

Subpregunta 4.a.1: Completa la tabla de clasificación con las dimensiones solicitadas.

Respuesta orientativa: Una solución posible para la clasificación es:

Lenguaje Implementación o entorno Modo de ejecución habitual Abstracción Paradigmas posibles Contextos representativos
C GCC u otro compilador C Compilación AOT a código nativo en el uso habitual. Alto nivel respecto al ensamblador; próximo al sistema comparado con Python o Java. Imperativo y procedimental. Sistemas, firmware y componentes con restricciones de recursos.
Python CPython Fuente a bytecode y ejecución en su máquina virtual; otras implementaciones pueden variar. Alto nivel. Imperativo, funcional y orientado a objetos. Automatización, análisis de datos, web y prototipos.
Java javac y JVM Compilación a bytecode y ejecución en JVM, con posible interpretación y JIT. Alto nivel. Principalmente orientado a objetos, también funcional e imperativo. Backend y aplicaciones empresariales sobre la JVM.
JavaScript Motor de navegador o Node.js Análisis y ejecución por un motor que puede usar interpretación y optimización JIT. Alto nivel. Imperativo, funcional y orientado a objetos basado en prototipos. Interfaz web y servicios de servidor con Node.js.
Ensamblador Ensamblador de una arquitectura concreta Traducción de mnemónicos a instrucciones de máquina para el destino. Muy bajo nivel; ligado a la arquitectura. Imperativo. Rutinas de bajo nivel, firmware o aprendizaje de arquitectura.

Las categorías de paradigmas se solapan: la tabla indica estilos que el lenguaje permite o suele usar, no una propiedad exclusiva. El nivel de abstracción también es relativo y el modelo de ejecución puede cambiar entre implementaciones.

Subpregunta 4.a.2: Recomienda un lenguaje para uno de los escenarios, indica al menos dos razones e incluye las limitaciones de tu recomendación.

Respuesta orientativa:

Las siguientes son recomendaciones posibles; otras respuestas son válidas si se justifican con los requisitos y se indican los compromisos:

  • Firmware de sensor con pocos recursos: C puede ser adecuado cuando se necesita controlar memoria, acceder a interfaces de bajo nivel y generar una imagen para el microcontrolador. Sus riesgos incluyen errores de memoria y mayor dependencia de la plataforma; habría que considerar también las herramientas y los requisitos concretos del dispositivo.
  • Interacción en el navegador: JavaScript es una elección directa porque los navegadores ofrecen motores JavaScript integrados y acceso a las API web. Para un proyecto real también se evaluarían accesibilidad, soporte, herramientas y mantenimiento.
  • Prototipo de análisis de datos: Python puede facilitar el desarrollo rápido y dispone de bibliotecas para datos. La selección depende de la compatibilidad, el tamaño del conjunto de datos, el rendimiento medido y el ecosistema requerido.

No es suficiente responder «el más popular» o «el más rápido»: hay que relacionar la elección con restricciones y necesidades verificables.

Ejercicio 5: prácticas generales de trabajo transferibles

Pregunta 5.a: Presenta al menos cinco prácticas de trabajo transferibles, con la evidencia observada y el error que ayudan a prevenir.

Respuesta orientativa:

Se pueden identificar, entre otras, estas prácticas:

  1. Registrar entorno y versiones. La salida de las herramientas de versión ayuda a reproducir el proceso y a explicar diferencias entre equipos.
  2. Comparar el mismo problema pequeño. Mantener la operación 5 + 7 permite atribuir las diferencias al lenguaje o al entorno, en vez de a algoritmos distintos.
  3. Separar fuente y artefactos generados. suma.c y Suma.java son fuentes; el ejecutable nativo y Suma.class tienen otro propósito. Así se evita tratar una salida antigua como el código editado recientemente.
  4. Registrar comandos y comprobar cada etapa. Se puede localizar si un fallo ocurre al compilar o al ejecutar y otra persona puede repetir la prueba.
  5. Leer los diagnósticos y corregir la causa. El mensaje puede indicar archivo, línea y tipo de error; ocultarlo o cambiar cosas al azar no demuestra que se haya resuelto.
  6. Predecir y verificar el resultado. La suma calculada a mano es 12; contrastarla con la salida permite detectar errores y conservar evidencia.
  7. Describir los límites de una clasificación. Nombrar CPython, JVM, Node.js o GCC evita generalizaciones sobre un lenguaje entero a partir de una única herramienta.
  8. Guardar evidencias y cambios con claridad. Fuentes, comandos y capturas o transcripciones bien identificadas facilitan revisión, comunicación y mantenimiento.

Son prácticas transferibles porque ayudan a reproducir, revisar y entender un proceso, aunque los comandos y los archivos cambien. Se relacionan con la sección «Buenas prácticas» de 1.5. Lenguajes de programación, en especial con describir la implementación, elegir según requisitos verificables, usar estilos con coherencia y documentar decisiones técnicas.

Ejercicio 6: entrega

Enunciado 6.a: Entrega un README.md identificado con tu nombre, módulo, unidad y práctica; incluye las respuestas, las tablas, las conclusiones, las versiones y los comandos. Añade los archivos fuente que hayas creado y una captura o transcripción de las salidas. Si una herramienta en línea oculta parte del proceso o no permite guardar un archivo generado, indícalo y aporta la evidencia disponible.

Comprobación del entregable: El README.md identifica a la persona o grupo, el módulo, la unidad y la práctica. Incluye las respuestas, la tabla de clasificación, las versiones y comandos utilizados, las evidencias de las salidas, la recomendación para el escenario y al menos cinco prácticas generales justificadas. Los archivos fuente deben corresponder a los ejemplos ejecutados. Si el entorno en línea no permite obtener un artefacto, el README debe dejar constancia de esa limitación y presentar la evidencia disponible.

Fuentes y referencias