25 julio 2008

Pasando de Delphi 7 a RAD Studio 2007 (3)

EL MODO SYNC EDIT

Si en el artículo anterior vimos como renombrar una variable utilizando las opciones de refactorización, ahora vamos a ver como hacerlo en tiempo real utilizando el modo Sync Edit.

Supongamos que quiero renombrar la variable i de este bloque de código:


Para renombrar rápidamente la variable i hacemos lo siguiente:

1. Seleccionamos todo el procedimiento:


2. Pulsamos el botón Sync Edit Mode que he señalado en la imagen superior y cambiará el color de la selección:


3. Como el cursor ya aparece situado en la variable i sólo tenemos que cambiarle el nombre de i por j:


4. Volvemos a pulsar el botón Sync Edit Mode que ahora está situado al principio del procedimiento y desaparecerá la selección dejando la variable renombrada.

Este modo esta pensado para estos casos en concreto. Si intentamos renombrar por ejemplo una variable de una clase en la interfaz no cambiará en su implementación, para ello ya tenemos que utilizar las opciones de refactorización que vimos en el artículo anterior. El modo Sync Edit sólo afecta al bloque de código seleccionado.

LAS PLANTILLAS DE CÓDIGO: LIVES TEMPLATES

Las plantillas de código nos permiten aumentar la productividad escribiendo código fuente mucho más rápido. Por ejemplo, nos ponemos a crear un bucle for:


Después de escribir la palabra for y pulsar la tecla de espacio nos traerá la plantilla que trae por defecto para la palabra for:


Escribimos la variable i y pulsamos el tabulador, lo que nos llevara al valor inicial:


Como quiero hacer un bucle desde 1 hasta 10, escribo 1 y vuelvo a pulsar el tabulador:


Ahora escribimos el valor 10 y quitamos el valor -1. Pulsamos Intro después de la palabra do nos creará arriba la variable automáticamente:


Cuando nos acostumbramos a este modo de trabajar se obtiene mucha velocidad y comodidad. De todas formas, si queremos escribir por libre sin utilizar la plantilla lo que tenemos que hacer es pulsar la tecla Escape en el momento que aparezca la plantilla. De ese modo vuelve a comportarse como un editor normal.

Igualmente tenemos una platilla para un bucle while:


Otra para la sentencia case:


Para ver todas las plantillas que hay definidas por defecto nos vamos al menú View -> Templates. Aparecerá esta ventana:


Si hacemos doble clic sobre cualquier plantilla la insertará directamente donde tengamos el código fuente:


Para modificar una plantilla pulsamos el botón Edit Code Template:


Se abrirá una nueva pestaña de código en el editor mostrando como está diseñada la plantilla en XML:


Para el bucle for la plantilla se llama fors.xml. Anteriormente hemos pulsado el tabulador para pasar de un punto a otro de la plantilla. Estos puntos están definidos dentro del archivo XML como point.


El valor que hay en hint es la etiqueta de ayuda que va a mostrar al usuario. Lo que voy a hacer yo ahora es predefinir el bucle for a mi gusto, de este modo cuando escriba la palabra for y pulse espacio mostrará esta plantilla:


Una de las plantillas que lleva predefinidas el editor de código y que es muy útil es cuando escribimos begin:


y pulsamos Intro:


Investigando un poco las plantillas estándar XML que hay definidas podemos desarrollar las nuestras propias para ganar velocidad al escribir código.

EL DEPURADOR DE CÓDIGO

El debugger también ha sufrido algunos cambios que van a mejor y que permiten averiguar los errores con mucha más rapidez. Cuando ejecutamos un programa con el botón:


o con la tecla F9, el debugger está activado por defecto, aunque se puede desactivar seleccionado en el menú superior Tools -> Options y en la ventana que aparece seleccionamos a la izquierda la sección Debugger Options y desactivamos la opción Integrated Debugging:


Supongamos que quiero depurar este bloque de código:


Lo que tenemos que hacer es pinchar con el botón izquierdo del ratón en la barra gris que hay a la izquierda del código para que aparezca el punto rojo que marca el inicio de la depuración (como se muestra en la imagen superior).

Cuando ejecutamos el programa y pasa por ese procedimiento se detiene en la línea donde hemos situado el punto de interrupción (el punto rojo):


Aparece una flecha azul en la parte izquierda (encima del punto rojo) que nos va a indicar la línea que se va a ejecutar en el programa. Para avanzar a la siguiente línea debemos pulsar la tecla F8. Los puntos azules que aparecen son las líneas por donde va a pasar el puntero de ejecución.

Al pulsar F8 para pasar a la siguiente línea dejará seleccionada la primera y saltará al bucle for:


La flecha azul se sitúa ahora al comienzo del bucle mientas que en la línea anterior que ha ejecutado nos pone una señal verde de confirmación para indicarnos que se ha ejecutado correctamente.

Como ya ha ejecutado la primera línea, si situamos el cursor del ratón encima de la variable c nos dirá su contenido:


Conforme vamos pulsando F8 y viendo como se va repitiendo el bucle también tenemos a la izquierda del editor de código una sección en la que nos muestra en tiempo real el contenido de las variables locales:


Podemos ver incluso el contenido del array bidimensional que he creado:


Si situamos el cursor encima de Mapa nos muestra todo el contenido del mismo permitiendo incluso observar el contenido de cada dimensión del array:


Este procedimiento que estamos monitorizando no contiene llamadas a otros procedimientos, pero si las tuviera podríamos entrar a los mismos pulsando el botón F7 en lugar de F8.

Podemos salir del modo de depuración con la tecla F9 que lo que hace es continuar la ejecución del programa o podemos detener el programa seleccionando Run -> Program Reset o pulsando la combinación de teclas CTRL + F2.

Veamos otro ejemplo un poco más complicado. Supongamos que tenemos un pedido con una serie de artículos. Lo vamos a controlar con estas dos clases:

type
TArticulo = class
ID: Integer;
sNombre: String;
rPrecio: Real;
end;

TPedido = class
ID: Integer;
sCliente: String;
Articulos: array[1..50] of TArticulo;
rTotal: Real;
end;

Ahora creamos un procedimiento que crea un pedido y le añade artículos:

procedure CrearPedido;
var
Pedido: TPedido;
begin
// Creamos el pedido
Pedido := TPedido.Create;
Pedido.ID := 1;
Pedido.sCliente := 'TRANSPORTES GARCIA, S.L.';

// Añadimos dos artículos al pedido
with Pedido do
begin
Articulos[1] := TArticulo.Create;
Articulos[1].ID := 1;
Articulos[1].sNombre := 'RUEDAS MICHELIN';
Articulos[1].rPrecio := 410.25;

Articulos[2] := TArticulo.Create;
Articulos[2].ID := 2;
Articulos[2].sNombre := 'FILTRO ACEITE';
Articulos[2].rPrecio := 176.12;

rTotal := Articulos[1].rPrecio + Articulos[2].rPrecio;

// Eliminamos los artículos
Articulos[2].Free;
Articulos[1].Free;
end;

// Eliminamos el pedido
Pedido.Free;
end;

Ahora situamos el punto de interrupción en la primera línea y vamos ejecutando el pedido con la tecla F8 hasta ejecutar la línea:

rTotal := Articulos[1].rPrecio + Articulos[2].rPrecio;


Si situamos el cursor encima del objeto Pedido podemos ir rastreando todo su contenido en tiempo real:


De este modo podemos ver la jerarquía de clases de un solo vistazo y sin tener que poner mensajes de depuración para ver su contenido. Esto es muy útil cuando queremos ver el contenido de los registros de las bases de datos que estamos procesando.

Por si esto fuera poco además podemos mirar a la izquierda la jerarquía y contenido de los objetos como si de un explorador se tratase:


Esto da mucha seguridad y potencia al programador para realizar una completa auditoria del código fuente en tiempo real, sobre todo cuando tenemos que modificar el código fuente que ha realizado otro programador y no tenemos ni idea de su comportamiento.

COMPROBANDO LAS PERDIDAS DE MEMORIA

Uno de los grandes problemas que tenemos en el lenguaje Object Pascal es que no libera automáticamente de memoria las variables y objetos que hemos creado (al contrario de otros lenguajes más modernos como Java, C#, Python, Ruby, etc.).

En las versiones de Delphi for Win 32 y RAD Studio tenemos disponible una variable global que permite averiguar que variables no hemos liberado al finalizar la ejecución del programa.

Al inicio de nuestro programa tenemos que activar esta variable:

ReportMemoryLeaksOnShutdown := True;

En el ejemplo del pedido que vimos anteriormente supongamos que no he liberado el artículo 2:

procedure CrearPedido;
var
Pedido: TPedido;
begin
ReportMemoryLeaksOnShutdown := True;

// Creamos el pedido
Pedido := TPedido.Create;
Pedido.ID := 1;
Pedido.sCliente := 'TRANSPORTES GARCIA, S.L.';

// Añadimos dos artículos al pedido
with Pedido do
begin
Articulos[1] := TArticulo.Create;
Articulos[1].ID := 1;
Articulos[1].sNombre := 'RUEDAS MICHELIN';
Articulos[1].rPrecio := 410.25;

Articulos[2] := TArticulo.Create;
Articulos[2].ID := 2;
Articulos[2].sNombre := 'FILTRO ACEITE';
Articulos[2].rPrecio := 176.12;

rTotal := Articulos[1].rPrecio + Articulos[2].rPrecio;

// Eliminamos los artículos
Articulos[2].Free;
//Articulos[1].Free;
end;

// Eliminamos el pedido
Pedido.Free;
end;

Como podéis ver en el código fuente he activado la variable global ReportMemoryLeaksOnShutdown para comprobar las perdidas de memoria.

Al finalizar la ejecución del programa nos aparecerá este mensaje:


Nos dice la clase de objeto que no hemos liberado y los bytes de memoria que se han perdido. El fallo que tiene es que no dice ni en que unidad se ha producido la pérdida de memoria y el número de líneas o procedimiento donde se produjo el error.

Esto es muy útil para zonas localizadas del programa cuando sabemos por donde anda el error, pero no es muy práctico en grandes proyectos donde no sabemos ni siquiera la unidad que está sufriendo las pérdidas de memoria.

Personalmente recomiendo utilizar el experto EurekaLog, que se integra perfectamente en cualquier versión de Delphi y le da cien vueltas al depurador de memoria de CodeGear.

En el próximo artículo seguiremos exprimiendo al máximo RAD Studio 2007.

Pruebas realizadas con RAD Studio 2007.

Publicidad