Cómo depurar un programa sencillo usando Netbeans.
¡Saludos a todos! Es un gusto para mí traerles un nuevo post, en esta ocasión, pensando en lo que, como a los estudiantes novicios, nos ha sucedido a todos: estás en clases, entiendes el problema, entiendes cómo se diseñó el algoritmo y por supuesto, cómo se escribió el código. Pero al llegar el turno de hacer las cosas por tu cuenta, no sabes ni por dónde empezar, y cuando ya llegas al código, por supuesto que te tienen que salir errores, y no tienes ni idea de cómo resolverlos. Es por eso que en esta entrada te mostraré, paso a paso, cómo corregir los errores en un programa.
El programa original
El programa debe realizar lo siguiente:
- Recibe como entrada dos variables tipo int: x, y.
- Almacena en z el residuo entero de dividir y entre x.
- Imprimir el valor de z
- Recibe dos variables flotantes de entrada: a y b.
- Almacena en c el resultado de multiplicar a y b.
- Imprime el valor de c.
- Recibe un valor String desde el teclado y lo almacena en nombre
- Imprime el objeto nombre.
En el archivo errores1Blog te presento el archivo original.
Aprovechando las ayudas visuales de Netbeans para solucionar errores.
Puede ser demasiado abrumador tratar de encontrar los errores, sobre todo para el programador novicio. Y aquí es donde entra en juego Netbeans, proporcionándonos ayudas visuales que harán más fácil la depuración del código. En la figura 1 te muestro el programa, pero ahora en la forma en que el editor de Netbeans lo despliega.

Figura 1. El programa original a depurar
Ahora, ya desde el principio, podemos notar lo que está sucediendo, y claramente algo no se ve bien: ¡todo el código se muestra en gris! Si has puesto atención a la forma en la que Netbeans utiliza los colores, recordarás que el texto en gris es la forma designada para visualizar los comentarios. El hecho de que el código se muestre en gris indica que todo está comentado, y para resolverlo sólo hace falta buscar en donde se abrió un comentario que no fue cerrado apropiadamente. Como puedes ver en la figura 2, esto sucede en la línea 13: ahí se abre un comentario de varias líneas, pero no se cierra, ya que en la línea 18 nuevamente se vuelve a abrir un comentario, pero ahora de una sola línea. Arreglemos este problema cerrando el comentario de líneas escribiendo */ en la línea 15.

Figura 1. El programa original a depurar
¡Quitando un error, ahora tenemos 10 más!
Ok, no te asustes, recuerda que esto es natural, de hecho, no deberías medir tu éxito en base al número de errores en tu código, porque entonces se vuelve muy frustrante aquello de que corregiste uno, pero ahora aparecen cien más. En muchos casos, el hecho de que tu código tuviera ese error que acabas de corregir hacía que Netbeans no pudiera detectar los demás errores, así que no te preocupes. ¡El éxito de un programa se debe medir de una forma más estricta: o funciona o no funciona!
En la figura 3 se muestra el nuevo programa:

Figura 1. El programa original a depurar
En la línea 5 se muestra una advertencia, no un error, por lo que la ignoraré (por el momento) e iré directamente a corregir los errores, los cuales se distinguen por el círculo rojo a la izquierda del número de línea, pero también por las palabras subrayadas en rojo.
Ahora podemos observar lo que sucede en la línea 22:
BufredReader bufer = new BufferedReader(new ImputStreamReader());
Observamos que simplemente está mal escrita la clase BufferedReader, así que hacemos el cambio correspondiente. Sigue marcando error, por lo que ahora nos concentramos en la clase InputStreamReader, la cual, además de estar mal escrita, se le debe pasar el argumento System.in, por lo que la línea 22 queda escrita:
BufferedReader bufer = new BufferedReader(new InputStreamReader(System.in));
Y esa línea sigue dando problemas. Ahora, aprovecho las ventajas de Netbeans, y clickeo sobre el foco de error sobre esta línea, y observo las sugerencias del IDE para corregir el error. (Figura 4). Casi siempre la mejor opción para resolver el error es la primera alternativa que te sugiere Netbeans, y éste es el caso, pues lo que está faltando en nuestro código es importar el paquete apropiado donde se encuentra la clase InputStreamReader (“Add import for java.io.InputStreamReader“). Ahora puedo proceder escribiendo la línea faltante, o simplemente haciendo click sobre la sugerencia, para que Netbeans agregue la línea por nosotros al inicio del programa, en la sección donde se importan los paquetes.

Figura 4. Sugerencias para corregir el error de la línea 22.
Y así queda libre de errores la línea 22.
¡Al fin avanzamos!
Pero aún tenemos varios errores. La figura 5 te muestro el programa después de corregir la problemática línea 22.

Figura 1. El programa original a depurar
Y si comparas la figura 3 con la 5, puedes observar que ahora tenemos una advertencia en la línea 27 que antes no se mostraba. Una vez más, recuerda que un error previo evita que el compilador revise líneas posteriores, por lo que esta situación es sumamente normal.
Nuevamente utilizo la ayuda de Netbeans, y coloco el mouse sobre el foco para ver las sugerencias. (Figura 6) En este caso, lo que me está diciendo es que la línea 27 va a generar una excepción (un error), por lo que se debe atrapar esta excepción y encerrarla en una cláusula throws. Ahora clickeo sobre el foco y de las sugerencias mostradas, selecciono la primera, añadir la cláusula throws para una excepción de entrada y salida (IOException).

Figura 1. El programa original a depurar
Al seleccionar esta alternativa, la advertencia de la línea 5 se debe apagar, pues precisamente se encendía debido a que se declaraba el paquete, pero nunca se hacía uso de la clase IOException.
Observa en la figura 7 los cambios que se hicieron: ya no marca advertencia en la línea 5, no hay error en la línea 27 y se añadió la cláusula throws en el encabezado del método main.

Figura 7. Nueva versión del programa después de corregir la línea 27
Continuamos…
Ahora nos movemos a la línea 28:
x= Integer.parseInt(entrada);
Al colocar el mouse sobre el foco rojo, nos indica que existe incompatibilidad de tipos. Analicemos cuál es el problema: x es una variable de tipo double, pero en la línea 28 se pide que el String entrada se convierta a entero. Para corregir este error, simplemente cambiamos el tipo de dato y el método de la siguiente forma:
x= Double.parseDouble(entrada);
Ahora veamos el error de la línea 33:
System.out.println("El residuo de dividir y ( + y + ") entre x ( " +x + ) es: " + z);
La explicación de error que el IDE nos da la puedes ver en la figura 8, pero aquí es donde pueden ponerse complicadas las cosas.

Figura 8: El error de la línea 33
A primera vista lo que se nos dice es que hace falta el ; con el que deben terminar las instrucciones de Java, pero si observas bien, la línea 33 sí termina con ;. Por eso es importante leer con detenimiento la sugerencia de NetBeans, pues más abajo dice: “No se puede encontrar símbolo”, e indica que el símbolo que no encuentra es la clase “entre”. Esto nos debe dar una guía sobre el error, por lo que tenemos que leer adecuadamente la línea 33 y recordar el esquema básico de la instrucción println:
System.out.println("mensaje" + variable + "mensaje");
Y claramente en la línea 28, esto no está sucediendo, partiendo de que lo que se desea ver en la pantalla es lo siguiente:
El residuo de dividir y ( 10 ) entre x ( " 2 + ) es: 0
Si suponemos que x = 2, y = 10. Entonces debemos re-escribir la línea 33 de la siguiente forma:
System.out.println("El residuo de dividir y (" + y + ") entre x ( " +x + ") es: " + z);
Nota las comillas dobles que se agregaron para cumplir con el esquema de “mensaje” + variable. Visualmente también puedes darte cuenta del error porque NetBeans coloca en amarillo los datos tipo cadena, observa la línea 33 de la figura 9.

Figura 9. El programa después de corregir la línea 33
Errores de las líneas 36, 37 y 39.
Ahora procedemos a revisar la línea 36, en donde nos encontramos con lo siguiente:
entrada = b.readLine();
Y NetBeans nos indica que la variable b no ha sido inicializada. Efectivamente b no ha sido inicializada, pero antes de darle un valor a b y pensar que con eso ya resolvimos el problema, analicemos un poco más la situación: el método readLine pertenece a un objeto de la clase BufferedReader, y b claramente no es un objeto (es una variable del tipo primitivo float). Además, ya hemos usado BufferedReader para leer valores desde el teclado, observa las líneas 27 y 30. Entonces este es un caso donde el programador se equivocó al escribir el nombre del objeto BufferedReader y por ello no debemos asignarle valor a b, sino más bien escribir lo siguiente:
entrada = bufer.readLine();
Eso soluciona el problema. Ahora vamos con la línea 37:
a = entrada;
Nuevamente el IDE nos indica que existe incompatibilidad de tipos, pues a es una variable tipo float y entrada es un objeto de la clase String.Usemos nuestra experiencia y volvamos a ver las líneas 28 y 31, en las que convertimos de String a un tipo primitivo de dato. Ahora queda más claro que este error se corrige de la siguiente forma:
a = Float.parseFloat(entrada);
(Más adelante escribiré un artículo dedicado a la clase BufferedReader para que estos errores queden entendidos)
Nos movemos a la línea 39, en la que tenemos:
in = bufer.readLine();
Y usamos nuestra experiencia con la clase BufferedReader y con las líneas anteriores, puesto que la descripción del error no nos ayuda mucho al indicarnos que “no se ha encontrado el símbolo in”. Bueno, claramente no hemos declarado ninguna variable ni objeto llamado in, pero si vemos las líneas 27 y 30, entendemos que debemos repetir el patrón asignando el objeto String entrada para que tome el valor de lo regresado por el método readLine(), y no declarar la variable in. Lo corregimos de la siguiente forma:
entrada = bufer.readLine();
Los errores de cadena y caracter
Hasta el momento, el programa corregido se muestra en la figura 10.

Figura 1o. El programa hasta el momento.
Nos quedan errores en las líneas 44, 45, 46 y 47. Pero antes de volvernos locos, observa cuidadosamente la línea 43. Ahí está una llave que cierra el método main. Puedes darte cuenta de ello por la línea negra vertical que va desde la línea 18 hasta la 43. Eso quiere decir algo muy grave: ¡las líneas 44 a la 47 no están incluídas dentro del método main! Por lo tanto no se ejecutarán, pero tampoco pueden quedarse ahí volando sin pertenecer a ningún método. Lo más lógico es quitar la llave de la línea 43 y colocarla en la línea 48. Esto nos deja el final del programa como se muestra en la figura 11.

Figura 11. Las últimas líneas del programa después de bajar la llave de la línea 43
En la línea 45 se nos indica que existe una advertencia, por lo que una vez más la ignoraré. No por no ser importante, sino porque generalmente se eliminan al corregir los errores posteriores. Por ello mi atención se va a la línea 46:
nombre = Entrada.ChartAt(12);
Aquí existen dos errores importantes. Para empezar, el objeto String que hemos estado utilizando para almacenar del bufer se llama entrada, no Entrada. Después, si recordamos los objetivos del programa al inicio de este post:
- Recibe un valor String desde el teclado y lo almacena en nombre
- Imprime el objeto nombre.
Nunca se nos dice que se debe almacenar en nombre sólo el caracter 12, por lo que cambio la línea por la siguiente:
nombre = entrada;
Pero ahora NetBeans protesta indicando que una variable no estática no puede ser referenciada en un contexto estático, como se observa en la figura 12. Este tipo de errores tiene validez cuando trabajamos con variables no estáticas, pero no es el caso, por lo que la forma más simple de corregir esto es meter la declaración de la variable entrada, la cual está fuera de main, en la línea 17 dentro del método main.

Figura 12. Error de la línea 46.
Y el último error, la línea 47, es muy simple: escribe correctamente el objeto: nombre y no Nombre.
Últimos detalles.
En este punto, ya han quedado resueltos todos los errores de sintaxis, y de hecho ya puedes ejecutar el programa. Pero aún no se encuentra 100% correcto. Los detalles que hacen falta cambiar son:
- En la línea 20, se deben declarar a las variables x, y, z como variables del tipo primitivo double y no como objetos de la clase Double.
- Y de hecho, x,y,z no deberían ser de tipo double, sino int, ya que los objetivos 1 y 2 del programa son:
- Recibe como entrada dos variables tipo int: x, y.
- Almacena en z el residuo entero de dividir y entre x
- Esto nos va a obligar a hacer los siguientes cambios:
- En la línea 20 escribir double en lugar de Double.
- Y en la 28 y 30 usar Integer.parseInt(entrada); en lugar de Double.parseDouble(entrada);
- Debemos cambiar la línea 32 de z = y / x; a z = y % x; Esto para ser consistente con los requisitos del programa. Ahí se pide el residuo y no la división entre dos números enteros.
- Por último, en la línea 44, el mensaje de salida debería solicitar un nombre y no una letra de la siguiente forma: System.out.println(“Escribe un nombre: “);
Y ahora sí, ya debe funcionar cumpliendo los requisitos del programa. En la figura 13 te muestro el programa final.

Figura 13. El programa corregido
Resultó una entrada muy larga, espero en un futuro poder hacer un video de este ejercicio de depuración. Aún así, espero que les haya sido útil. Les comparto el código del programa original (errores1Blog) para que puedan practicar siguiendo los pasos para corregir el programa, pero más que llegar a la corrección del mismo, me interesaba más compartir con ustedes el proceso de depuración, pues realizando este proceso constantemente vas a ir adquiriendo experiencia.
Recuerden que si tienen dudas escriban sus comentarios, y consideren compartir esta entrada en sus redes.
¡Hasta la próxima!
Eric Hernandez Hernandez 1A DSM
José Alfredo González Pozos