|
Pràctica 4: Depuració |
En aquesta pràctica treballarem sobre un projecte relativament complex, potser un xic més que els que hem fet fins ara. Això ens ajudarà a aprendre coses noves de Java especialment algunes tècniques de depuració dels nostres projectes, que facin possible el seguiment i correcció senzilla dels inevitables errors de programació. | |||||
Ens vigilen! |
|||||
Imagineu que rebem l'encàrrec d'escriure el programari per a un sistema de control de personal adaptat a les necessitats d'un institut. L'encàrrec implica que:
Per a resoldre aquest problema amb senzillesa, necessitem pensar acuradament en quines peces necessitem. Aquest és el diagrama que suggerim:
|
|||||
Obre el i crea un nou projecte amb el nom presencia. Ves afegint les classes que es detallen més avall. Revisa el codi de cadascuna per a verificar la feina que fan. | |||||
A) Moviment | |||||
Aquesta classe Moviment volem que reculli l'estructura informativa de les entrades i sortides d'alumnes. Què necessitem saber d'un moviment?
Aquesta n'és una traducció en Java:
|
|||||
/** * Estructura d'un moviment. * Conté informació sobre qui fa el moviment, en quina data * i si és entrada (entrada=true) o sortida (entrada=false) * * @author angel solans * @version 15-04-2004 */ public class Moviment { // Codi d'estudiant private String estudiant; // Hora en que es produeix el moviment private java.util.Date hora; // És una entrada o una sortida? private boolean entrada; /** |
|||||
Aquest tipus de classes, que descriuen la forma d'un objecte sense fer res més i, per tant, contenen només constructor/s, camps privats i mètodes accessors als camps (getters i setters), reben el nom de POJO (Plain Old Java Object). Moltes eines de Java treballen amb pojos. És bo, doncs, que sempre intentis descriure els objectes que fas en forma de pojo. Observa que definim tres camps: estudiant, hora i entrada.
La informació del constructor és important: per defecte un moviment el definim com a entrada i, en crear l'objecte, fem l'assignació de l'hora actual. Així no ens cal patir per a gestionar l'hora en què es produeix el moviment: serà la mateixa hora de la creació de l'objecte Moviment. Com que aquesta hora ja no s'ha de canviar més, ja no hem escrit un mètode "setter" -setHora()- per aquest camp. Fixa't, en canvi, que sí que disposem d'un mètode getHora(). |
|||||
B) Servidor | |||||
Seguidament, creem una classe que s'encarrega d'enregistrar les entrades i sortides d'alumnes i de facilitar la informació als pares. És el cor del programa, la classe Servidor. Afegeix-la al projecte presencia. |
|||||
/** * Gestiona el registre d'accessos a l'institut i * en dóna la informació als pares * * @author Angel Solans * @version 15-04-04 */ public class Servidor { //Llista d'accessos del dia actual private static java.util.Vector registre = new java.util.Vector(); /** /** |
|||||
Observa els detalls importants d'aquest codi:
|
|||||
/** * Entrada d'un estudiant a l'institut. * S'enregistra l'estudiant que ha entrat i l'hora * * @param estudiant codi de l'estudiant; */ public void entra(String estudiant) { Moviment moviment = new Moviment(); moviment.setEstudiant(estudiant); registre.add(moviment); } |
|||||
|
|||||
moviment.setEntrada(false); | |||||
|
|||||
|
|||||
Modifica el mètode supervisa
perquè ens retorni la data en els formats següents:
|
|||||
C) Les targetes de pares i estudiants | |||||
La targeta dels estudiants només serveix per a fitxar a l'entrar
i al sortir de l'institut. Afegeix la classe al projecte: |
|||||
/** * Targeta de l'estudiant * * @author Angel Solans * @version 15-04-2004 */ public class EstudiantClient { private String estudiant; /** /** |
|||||
Les targetes dels pares només executes el mètode supervisa(), que crida el mètode supervisa() del servidor. Afegeix la classe al projecte: | |||||
/** * Targeta per als pares * * @author Angel Solans * @version 15-04-2004 */ public class PareClient { //
Codi d'estudiant /** /** |
|||||
|
|||||
El Depurador | |||||
El codi del projecte de control de presència és senzill, molt simple si el comparem a un projecte de la vida real. És fàcil de depurar: si comets un error, segurament trobaràs l'origen amb facilitat. Però això no sempre és així. Pràcticament tots els entorns de programació incorporen eines de depuració per a facilitar la correcció i control de les aplicacions. Alguns depuradors són molt sofisticats, altres força senzills. incorpora un depurador elemental, molt fàcil d'utilitzar. Malgrat la pobra aparença, et resultarà més que suficient per a treballar amb la major part de programes que puguis escriure. La feina més habitual del depurador consisteix en posar punts de ruptura en el programa.
Ara posarem el depurador en marxa. Abans, però, observa el mètode següent que hem inclòs a la classe Servidor: |
|||||
/** |
|||||
Crea algunes targetes d'estudiant i fes alguns moviments, després crea una instància de la classe Servidor i executa el mètode getEntrades(). Obtindràs un error en temps d'execució, un ArrayIndexOutOfBoundsException. Tot i que estem convençuts que has trobat l'error en el codi d'un cop d'ull, imagina que és la darrera hora de la teva jornada laboral i estàs una mica espès: pots recórrer al depurador per a localitzar l'error. Obre la classe Servidor, activa l'editor i
ves al mètode getEntrades(). Faràs
que el flux normal del programa s'aturi en una línia determinada
per a repassar els valors de les variables i executar el programa línia
a línia fins a trobar l'error. Com que d'entrada no tens massa
idea d'on cau l'error, posaràs el punt de ruptura al començament
del mètode. Busca la línia en el mètode getEntrades(). És la primera línia. Observa l'editor; a l'esquerra tens una petita columna. Fes un clic sobre la columna a l'alçada de la línia indicada. Si has encertat amb el ratolí, t'apareixerà un senyal d'stop a l'esquerra de la línia: acabes de triar un punt de ruptura pel programa. Ara tanca l'editor i torna a la interfície principal del . Tria l'opció de menú Veure | Mostrar Depurador (o fes Ctrl + D). T'ha de sortir una finestra com aquesta: |
|||||
És la finestra de depuració. Treballarem amb ella. Torna a la finestra principal del i posa el projecte a treballar si encara no ho has fet: crea alguns estudiants i fes-los entrar a l'institut. Crea una instància de la classe Servidor. Executa el mètode getEntrades(). Immediatament ens salta la finestra de depuració a primer pla: |
|||||
Ara ja pots manipular el depurador. Observa que disposes de diferents caixes on es llisten, separadament
En el moment que obrim el depurador, només és actiu un camp, la llista de moviments. És el vector que apareix a la caixa de variables estàtiques. Fes un doble clic sobre el seu nom: s'obrirà l'inspector d'objectes i podràs estudiar l'estat del vector. Observa que el programa està aturat. Està esperant les teves ordres perquè ara tens el control de flux de l'aplicació. Clica sobre el botó Pas i el programa saltarà una línia. Si a la línia següent hi ha una crida a un mètode, picant sobre el botó Pas Endins el depurador entrarà a l'interior del mètode cridat i també podràs depurar-lo. Si vols que el programa continui amb normalitat, pica sobre el botó Continuar. Per a localitzar l'error en el mètode, fes correr el programa
pas a pas. Aniràs recorrent línies fins arribar al bucle
d'impressió de dades. Observa que, caminant pas a pas, pots extreure
totes les dades del vector fins que, arribant al darrer element, el bucle
intenta localitzar un moviment més enllà dels límits
del vector: aquest és l'error.
|
|||||
if (registre!=null) for (int n=0;n<=registre.size();n++) { | |||||
Has de modificar el codi, no ha de ser | |||||
n<=registre.size() | |||||
sinó | |||||
n<registre.size() | |||||
de manera que la línia ha de dir: | |||||
if (registre!=null) for (int n=0;n<registre.size();n++) | |||||
&nbs |