El proceso de desarrollo
Valentina programó la app de la cantina del liceo. La probó con su pedido y andaba perfecto. El primer día de uso, un compañero pidió algo con cantidad 0 y la app se trancó. ¿Cómo se organiza el trabajo para que esto no pase, y qué hacés cuando igual pasa? Ningún programa nace terminado ni funciona a la primera: entre la idea y el programa confiable hay un proceso con etapas que se repiten. Dominar ese proceso es tan importante como saber escribir código.
El ciclo de desarrollo
En la práctica no se escribe todo el programa y recién después se prueba. Se trabaja con desarrollo incremental: primero una versión mínima que ande (por ejemplo, que la app solo muestre el menú), se prueba, y después se agrega una funcionalidad por vez, recorriendo el ciclo en cada una. Si algo falla, el error está en lo último que agregaste, y eso lo hace mucho más fácil de encontrar.
Estas fases del desarrollo de un programa están desordenadas: (a) probar el programa con distintos datos, (b) editar el código fuente, (c) depurar los errores…
Estas fases del desarrollo de un programa están desordenadas: (a) probar el programa con distintos datos, (b) editar el código fuente, (c) depurar los errores encontrados, (d) ejecutar el programa. Ordenalas de forma razonable y explicá qué se hace en cada una, teniendo en cuenta que al probar puede ser necesario volver atrás.
Explicá qué es un «bug» en un programa y qué es depurar. Poné un ejemplo sencillo de error que podría tener el programa de un cajero automático y qué consecuencia…
Explicá qué es un «bug» en un programa y qué es depurar. Poné un ejemplo sencillo de error que podría tener el programa de un cajero automático y qué consecuencia tendría para el usuario.
La figura muestra el ciclo de trabajo del desarrollo de un programa, pero una de sus etapas está tapada con un signo de interrogación, como se muestra en la figura.…
La figura muestra el ciclo de trabajo del desarrollo de un programa, pero una de sus etapas está tapada con un signo de interrogación, como se muestra en la figura.
Indicá qué etapa falta dentro del ciclo, en qué consiste y por qué la flecha de «no» devuelve el trabajo a la edición del código.
Tipos de error
Un bug es cualquier error de un programa, y depurar es encontrarlo y corregirlo. Si un cajero automático descuenta el monto dos veces, ese es un bug con una consecuencia muy concreta: el usuario pierde plata.
En lenguajes compilados, los errores de sintaxis aparecen al compilar (el programa ni siquiera se genera). En lenguajes interpretados como Python, aparecen al llegar a esa línea. Los de ejecución y los de lógica, en cambio, solo se ven al correr el programa.
Distinguí entre un error que aparece al compilar (el programa ni siquiera arranca) y un error que aparece en ejecución (arranca pero falla con ciertos datos), con un…
Distinguí entre un error que aparece al compilar (el programa ni siquiera arranca) y un error que aparece en ejecución (arranca pero falla con ciertos datos), con un ejemplo de cada tipo.
Explicá la diferencia entre un error de sintaxis y un error de lógica, con un ejemplo de cada uno en un programa que calcula el promedio de tres notas. ¿Cuál de los dos…
Explicá la diferencia entre un error de sintaxis y un error de lógica, con un ejemplo de cada uno en un programa que calcula el promedio de tres notas. ¿Cuál de los dos tipos impide ejecutar el programa y cuál deja ejecutarlo pero da resultados incorrectos?
Diseñar casos de prueba
Por ejemplo, para un programa que suma dos números, un caso normal es la entrada 3 y 4 con resultado esperado 7; un caso especial es 0 y -5 con resultado esperado -5.
Explicá qué es un caso de prueba y escribí dos casos para un programa que suma dos números: uno con valores normales y otro con algún valor especial, indicando la…
Explicá qué es un caso de prueba y escribí dos casos para un programa que suma dos números: uno con valores normales y otro con algún valor especial, indicando la entrada y el resultado esperado de cada uno.
Un programa que divide dos números funciona bien en casi todas las pruebas, pero falla cuando el divisor es 0. Explicá qué son los valores límite o casos especiales en…
Un programa que divide dos números funciona bien en casi todas las pruebas, pero falla cuando el divisor es 0. Explicá qué son los valores límite o casos especiales en las pruebas, por qué hay que probarlos siempre y citá otros dos valores con los que probarías este programa.
Para probar un programa que aplica un descuento a personas de 65 años o más, definí tres casos de prueba: uno con un valor normal, uno con el valor límite exacto y uno…
Para probar un programa que aplica un descuento a personas de 65 años o más, definí tres casos de prueba: uno con un valor normal, uno con el valor límite exacto y uno con un valor erróneo (edad negativa o imposible), con el resultado esperado de cada uno. Justificá tus elecciones.
Un compañero de equipo te muestra la siguiente función en C++ para calcular el precio final con IVA y aplicar un descuento si el cliente es socio, asegurando: «Si…
Un compañero de equipo te muestra la siguiente función en C++ para calcular el precio final con IVA y aplicar un descuento si el cliente es socio, asegurando: «Si compila sin errores ni advertencias, es imposible que falle en ejecución; no hace falta probarla»:
float calcularPrecioFinal(float base, bool esSocio) {
float total = base;
if (esSocio = true) {
total = total * 0.90f;
}
total = total * 1.21f;
return total;
}
-
Predecí razonadamente la salida de la función para un cliente no socio (
esSocio = false) con una base de 100,00 pesos. ¿Coincide con el comportamiento esperado? Explicá por qué el compilador no lo rechaza como error. -
Justificá, a partir de este ejemplo, la diferencia entre lo que garantiza la verificación sintáctica del compilador y lo que demuestran las pruebas dinámicas de software.
-
Proponé la corrección del código y escribí un caso de prueba concreto que evidencie el fallo si la corrección no estuviera aplicada.
Diseñá un plan de pruebas para un programa que pide dos números y muestra su división: hacé una tabla con al menos seis casos de prueba (pares de valores de entrada,…
Diseñá un plan de pruebas para un programa que pide dos números y muestra su división: hacé una tabla con al menos seis casos de prueba (pares de valores de entrada, incluyendo valores normales, límite y erróneos), el resultado esperado de cada uno y qué debería hacer el programa si la entrada no es válida. Justificá la elección de cada caso.
La intranet del liceo implementa un módulo de autenticación con los siguientes requisitos: Nombre de usuario: de 4 a 12 caracteres alfanuméricos, insensible a…
La intranet del liceo implementa un módulo de autenticación con los siguientes requisitos:
-
Nombre de usuario: de 4 a 12 caracteres alfanuméricos, insensible a mayúsculas/minúsculas.
-
Contraseña: entre 8 y 16 caracteres, sensible a mayúsculas/minúsculas, con al menos un dígito y un carácter especial.
-
Seguridad: bloqueo temporal de la cuenta durante 15 minutos tras tres intentos fallidos consecutivos.
Diseñá un plan de pruebas riguroso mediante una tabla con al menos seis casos de prueba diseñados por vos. Para cada caso tenés que especificar: identificador, valores de entrada (usuario y contraseña), estado previo del sistema, resultado esperado y qué riesgo específico de lógica, frontera o seguridad estás validando.
Un programador sostiene que «una función de una sola línea no necesita pruebas porque es autoevidente» y presenta esta función escrita en C++: 1. Predecí la salida de la…
Un programador sostiene que «una función de una sola línea no necesita pruebas porque es autoevidente» y presenta esta función escrita en C++:
bool esImpar(int n) {
return (n % 2 == 1);
}
-
Predecí la salida de la función para
n = 7,n = 0yn = -7. Explicá técnicamente por qué se produce un resultado inesperado en uno de ellos basándote en cómo implementa el operador módulo (%) los operandos negativos en este lenguaje. -
Corregí la expresión para que la función sea matemáticamente correcta con cualquier número entero.
-
Apoyándote en este caso, rebatí con dos argumentos técnicos la idea de prescindir de pruebas unitarias en algoritmos breves o aparentemente triviales.
Técnicas de depuración
Explicá qué es un mensaje de traza o registro (log) en un programa y cómo ayuda a encontrar un error (permite ver por dónde pasó el programa y con qué valores).
Explicá qué es un mensaje de traza o registro (log) en un programa y cómo ayuda a encontrar un error (permite ver por dónde pasó el programa y con qué valores).
Un bucle de un programa no se detiene nunca. Explicá dónde colocarías mensajes de escritura temporales para diagnosticarlo (dentro del bucle, mostrando la variable de…
Un bucle de un programa no se detiene nunca. Explicá dónde colocarías mensajes de escritura temporales para diagnosticarlo (dentro del bucle, mostrando la variable de control en cada vuelta) y qué observarías en esos mensajes para encontrar la causa.
En el sistema de cobro de una cooperativa del liceo se ha detectado que, al emitir la factura mensual, el total a pagar de algunos socios es erróneo. Disponés de los…
En el sistema de cobro de una cooperativa del liceo se ha detectado que, al emitir la factura mensual, el total a pagar de algunos socios es erróneo. Disponés de los siguientes registros del sistema:
-
Socio 101: 2 compras de 15,00 pesos -> Total cobrado: 30,00 pesos (esperado: 30,00 pesos).
-
Socio 102: 1 compra de 50,00 pesos con descuento promocional del 10 % (5,00 pesos) y recargo por gastos de gestión de 3,00 pesos -> Total cobrado: 47,50 pesos (esperado: 48,00 pesos).
-
Socio 103: 1 compra de 20,00 pesos y devolución de 1 artículo de 5,00 pesos (-5,00 pesos) -> Total cobrado: 25,00 pesos (esperado: 15,00 pesos).
-
Formulá una hipótesis justificada sobre el fallo lógico o de orden de operaciones que explica el error en el Socio 102 y en el Socio 103.
-
Diseñá la estrategia de depuración para confirmar tus hipótesis: indicá qué datos de prueba mínimos introducirías para aislar el fallo, en qué puntos del flujo situarías puntos de interrupción (breakpoints) y qué variables concretas deberías inspeccionar paso a paso.
Modularizar, documentar y buenas prácticas
Dos refactorizaciones típicas: renombrar variables (x pasa a precio) y extraer una función cuando el mismo cálculo está copiado en varios lugares (el cálculo del IVA del 22 % se escribe una sola vez y se la llama donde haga falta). No hace falta formalizarlo más: alcanza con que el código quede más claro y siga haciendo lo mismo.
Buenas prácticas y documentación
-
Nombres claros: que digan qué guarda la variable o qué hace la función.
-
Comentarios útiles: explican el porqué de una decisión, no repiten lo que ya dice el código.
-
Documentación: acompaña al programa y explica como mínimo qué hace y cómo se usa. Sin ella, cuando alguien nuevo se suma al equipo (o vos mismo volvés al proyecto meses después) hay que adivinar todo, y el programa «envejece» mal.
Trabajo en equipo y control de versiones
Cuando varias personas trabajan en el mismo proyecto, modularizar permite repartir el trabajo en partes independientes y probarlas por separado. Para no pisarse, se usa un sistema de control de versiones como Git (con GitHub como sitio donde se comparte el repositorio). Cada cambio se guarda como una versión (versión 1, versión 2, versión 3…), así que si la última versión anda peor que la anterior, podés volver atrás.
Los programas tienen versiones (1.0, 1.1, 2.0...). Explicá para qué sirve guardar versiones del código y qué podés hacer si la última versión funciona peor que la…
Los programas tienen versiones (1.0, 1.1, 2.0...). Explicá para qué sirve guardar versiones del código y qué podés hacer si la última versión funciona peor que la anterior.
La documentación acompaña al programa. Explicá qué dos cosas debería explicar como mínimo (qué hace el programa y cómo se usa) y por qué un programa sin documentar…
La documentación acompaña al programa. Explicá qué dos cosas debería explicar como mínimo (qué hace el programa y cómo se usa) y por qué un programa sin documentar «envejece» mal cuando trabaja un equipo.
Explicá qué es la modularización de un programa (dividirlo en funciones o módulos) y analizá dos ventajas que aporta cuando el desarrollo lo hace un equipo de varias…
Explicá qué es la modularización de un programa (dividirlo en funciones o módulos) y analizá dos ventajas que aporta cuando el desarrollo lo hace un equipo de varias personas: pensá en el reparto del trabajo, en las pruebas y en la localización de errores.
Explicá qué es refactorizar (mejorar el código sin cambiar lo que hace) y describí dos refactorizaciones típicas (renombrar variables con nombres claros, extraer una…
Explicá qué es refactorizar (mejorar el código sin cambiar lo que hace) y describí dos refactorizaciones típicas (renombrar variables con nombres claros, extraer una función a partir de código repetido), con un ejemplo de cada una.
Un fragmento de código usa las variables x, y2 y zzz para guardar el precio, el IVA y el total. Reescribí esos nombres de forma significativa y explicá por qué la…
Un fragmento de código usa las variables x, y2 y zzz para guardar el precio, el IVA y el total. Reescribí esos nombres de forma significativa y explicá por qué la elección de nombres es una herramienta contra los errores (el código se autodocumenta).
Dos personas de un equipo editan a la vez el mismo archivo del proyecto y, al unir los cambios, aparece un conflicto. Explicá qué es un conflicto de fusión, cómo se…
Dos personas de un equipo editan a la vez el mismo archivo del proyecto y, al unir los cambios, aparece un conflicto. Explicá qué es un conflicto de fusión, cómo se resuelve (revisar ambas versiones y decidir) y qué dos hábitos de trabajo en equipo lo previenen (repartir el trabajo por módulos, integrar los cambios a menudo).
El sistema de supervisión de un invernáculo se programó en un único archivo dentro de una sola función de 400 líneas. El código lee de forma secuencial tres sensores…
El sistema de supervisión de un invernáculo se programó en un único archivo dentro de una sola función de 400 líneas. El código lee de forma secuencial tres sensores analógicos de humedad de suelo, calcula el promedio, evalúa umbrales, acciona una electroválvula mediante un pin digital, guarda el registro histórico en un archivo de texto y envía un correo de alerta si la humedad cae por debajo del 30 %.
-
Justificá detalladamente tres problemas técnicos graves que genera esta arquitectura cuando se necesita depurar un fallo intermitente o realizar pruebas unitarias automatizadas.
-
Diseñá una refactorización modular del programa: descomponé la función en al menos cuatro funciones independientes. Para cada una definí su nombre, parámetros de entrada con tipo, valor devuelto y su responsabilidad única.
-
Explicá cómo permitiría tu diseño probar el algoritmo de decisión de riego mediante simulación de datos, sin tener los sensores físicos conectados a la placa.
Un grupo de tres estudiantes va a desarrollar durante diez semanas una aplicación de control de asistencia para el liceo. Para evitar retrasos y entregas fallidas de…
Un grupo de tres estudiantes va a desarrollar durante diez semanas una aplicación de control de asistencia para el liceo. Para evitar retrasos y entregas fallidas de último momento, tenés que estructurar la metodología de trabajo del equipo:
-
Diseñá un cronograma organizado en cuatro hitos o entregables verificables, explicando qué criterios objetivos deben cumplirse antes de autorizar el paso al hito siguiente.
-
Definí un protocolo formal de revisión por pares (code review): establecé quién revisa el código de quién, qué lista de comprobación de calidad mínima debe superarse antes de aceptar cualquier cambio y cómo se gestionan los desacuerdos.
-
Establecé y justificá una política de «congelación de código» (code freeze): en qué semana debe activarse, qué tipo de modificaciones quedan terminantemente prohibidas a partir de ese momento y qué tareas exclusivas debe asumir el equipo hasta la entrega final.
Reto del tema. Como analista júnior de software, vas a diseñar un script en Python (podés usar un entorno web gratuito como Replit) que evalúe el costo energético diario…
Reto del tema. Como analista júnior de software, vas a diseñar un script en Python (podés usar un entorno web gratuito como Replit) que evalúe el costo energético diario para promover el ahorro doméstico.
Seguí estas tres fases:
-
Captura de datos: Entrá en la web de UTE (Administración Nacional de Usinas y Trasmisiones Eléctricas) y registrá el precio oficial ($\$/\text{kWh}$) de $6$ franjas horarias distintas del día de hoy.
-
Diseño y codificación: Aplicá el proceso de desarrollo de software. Esbozá primero el algoritmo y trasladalo a Python. El programa debe almacenar los datos en una lista, usar un bucle iterativo para calcular el costo medio diario y emplear condicionales (
if-else) que emitan alertas cuando el precio supere el umbral de $0,18$ pesos/kWh. -
Depuración y producto final: Realizá pruebas con valores límite y corregí fallos de ejecución. Redactá un informe breve que incluya el código limpio y comentado, una captura del resultado en la consola y dos propuestas de consumo eficiente para tu hogar basadas en tus datos.
Se valorará:
-
Rigor en el proceso de desarrollo (diseño algorítmico previo, codificación textual y depuración).
-
Uso correcto de estructuras de control (secuenciales, condicionales e iterativas) y sintaxis del lenguaje.
-
Precisión en el tratamiento de datos reales y viabilidad de las conclusiones energéticas.
Resumen
Volvé al principio: la app de Valentina falló con cantidad 0 porque solo se probó con un pedido normal. Con casos límite y erróneos, y con el ciclo repetido en cada paso, ese fallo aparece antes de publicar.