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.

18 julio 2008

Pasando de Delphi 7 a RAD Studio 2007 (2)

Sigamos viendo las novedades de RAD Studio respecto a Delphi 7.

EL EDITOR DE CODIGO FUENTE

Esta es una comparativa entre el editor de código de Delphi 7 y RAD Studio 2007:


La primera característica que puede apreciarse es en la barra lateral situada a la izquierda del código fuente. Mientras que Delphi 7 sólo mostraba la posición de la línea y columna actual en la parte inferior del editor de código, en RAD Studio podemos ver siempre el número de línea donde estamos situados. Además, también muestra el número de línea cada 10 líneas.

Otra novedad que destaca se encuentra en la línea lateral de color verde. Esta línea nos informa en todo momento del código fuente que se ha modificado y si se ha guardado o no.

Por ejemplo, si yo creo una variable privada, me mostrará en amarillo las líneas afectadas por la modificación:


Cuando pulse el botón de guardar volverán a estar todas las líneas en color verde, preparado para más modificaciones:


También otra novedad importante que da más claridad al código fuente es la posibilidad en abrir y cerrar bloque de código. Por ejemplo este bloque código fuente está abierto:


Si pulsamos el botón [-] que se indica en la foto superior contraerá toda la definición de la clase TForm1 dejando menos líneas de código en pantalla:


El botón [-] ha sido sustituido por el botón [+] para poder desplegar el código de nuevo. El funcionamiento es similar a otros entornos de desarrollo como Visual Studio, NetBeans, Eclipse, etc.

Así mismo, podemos contraer o estirar todos los bloques de código de la unidad en la que estamos situados pulsando con el botón derecho del ratón sobre el código fuente y seleccionando la opción Fold:


Podemos contraer métodos, tipos de datos, etc.

Lo mismo para volver a desplegarlo todo:


La barra de estado inferior del editor de código también tiene algunas novedades:


En la parte izquierda de la barra incorpora tres botones para la grabación y la reproducción de macros. Una macro puede ser desde una acción con los menús de Delphi o incluso escribir un código fuente que luego tenemos que repetir. Es decir, graba todas las acciones de teclado o ratón que se realicen en Delphi para su posterior reproducción.

Después tiene las mismas coordenadas de fila y columna que tenía Delphi 7 y el estado al escribir: Insertar o Modificar. Por último, finaliza con tres pestañas:

Code: Muestra el editor de código.

Design: Muestra el formulario.

History: Muestra el histórico de versiones del código fuente de la unidad actual.

EL HISTORIAL DE VERSIONES

La pestaña History es otra de las novedades que incorporan las versiones Delphi para Win32 y superiores:


Para cada unidad de código, RAD Studio realiza automáticamente un control de versiones para poder recuperar el código fuente de modificaciones anteriores.

Cuando hemos pulsado las pestaña History ha dividido el editor de código fuente en dos partes. La parte superior muestra las distintas versiones que almacena de la unidad donde estamos:


La última versión es File y el resto va en orden descendente. En entorno de RAD Studio viene configurado por defecto para guardar hasta 10 versiones de cada unidad. Aunque podemos modificar esto seleccionando Tools -> Options y en la sección Editor Options tenemos el campo File backup limit:


Vamos a verlo con un ejemplo. Supongamos que añado la variable sDireccion a mi clase TForm1:


Si pulsamos la pestaña History podemos ver la última versión pulsando sobre la primera fila del histórico (File):


Pero si seleccionamos la versión 3 (la segunda fila) me mostrará como estaba el código fuente antes de realizar el último cambio:


Como sabemos por la configuración que guarda hasta los 10 últimos cambios, podemos modificar el programa a nuestro antojo sin miedo a rectificar el código actual. Todos estos cambios los va guardando realmente en una carpeta llamada __history que esta situada en el mismo directorio de nuestro proyecto.

Si queremos recuperar una versión anterior sólo hay que seleccionarla con el botón derecho del ratón y seleccionar Revert:


Nos pedirá confirmación por si acaso:


Una vez pulsemos el botón Yes dejará el código fuente exactamente como estaba en esa versión.

REFACTORIZANDO BLOQUES DE CÓDIGO

Esta es otra de las mejores características que incorpora respecto a Delphi 7. Como todos sabéis, refactorizar el código fuente significa crear funciones o procedimientos comunes que simplifiquen y reduzcan el número de líneas de código. Vamos a verlo con un ejemplo.

Supongamos que tengo un procedimiento con dos bucles que hacen casi lo mismo:

procedure TForm1.Facturar;
var
i: Integer;
begin
for i := 1 to iNumeroPedidos do
begin
MarcarDocumento( i );
CrearFactura;
ActualizarMovimientos;
end;

for i := 1 to iNumeroAlbaranes do
begin
MarcarDocumento( i );
CrearFactura;
ActualizarMovimientos;
end;
end;

Para simplificar este procedimiento habría que hacer otro procedimiento común llamado FacturarDocumento que ejecutará cada una de las tres líneas de cada bucle. Hasta ahora lo hemos hecho a mano, pero vamos a ver como se simplifica el proceso con RAD Studio.

Ahora podemos refactorizarlo de la siguiente manera:

1. Seleccionamos las tres líneas del primer bucle:


2. Pinchamos con el botón derecho del ratón sobre las líneas seleccionadas y elegimos Refactoring -> Extract Method:


Aparecerá esta ventana:


2. En el campo New Method Name escribimos FacturarDocumento y pulsamos el botón Ok. El código fuente quedará de este modo:

procedure TForm1.FacturarDocumento(i: Integer);
begin
MarcarDocumento(i);
CrearFactura;
ActualizarMovimientos;
end;

procedure TForm1.Facturar;
var i: Integer;
begin
for i := 1 to iNumeroPedidos do
begin
FacturarDocumento(i);
end;

for i := 1 to iNumeroAlbaranes do
begin
MarcarDocumento( i );
CrearFactura;
ActualizarMovimientos;
end;
end;

Lo que ha hecho es crear el nuevo método llamado FacturarDocumento que se ha llevado las tres líneas del bucle y las ha reemplazado por una llamada a este nuevo método. Ahora sólo queda quitar los begin y end del primer bucle y hacer lo mismo con el segundo:

procedure TForm1.FacturarDocumento(i: Integer);
begin
MarcarDocumento(i);
CrearFactura;
ActualizarMovimientos;
end;

procedure TForm1.Facturar;
var
i: Integer;
begin
for i := 1 to iNumeroPedidos do
FacturarDocumento(i);

for i := 1 to iNumeroAlbaranes do
FacturarDocumento(i);
end;

Como puede apreciarse, la refactorización ha sido un éxito y nos ha llevado poco tiempo. Quizás en programas tan pequeños como este no se note demasiado, pero en unidades de miles de líneas os puedo asegurar que es una bendición.

También se puede hacer más rápido del siguiente modo: seleccionas el bloque de código que quieres sacar a parte y luego pulsas la combinación de teclas Mayúsculas + CTRL + M. Después pulsas Intro y ya esta.

DECLARANDO VARIABLES AUTOMÁTICAMENTE

Otra de las características que incorporan las opciones dedicadas a la refactorización es la posibilidad de declarar automáticamente en la sección var las variables que utilizamos en un bloque de código.

Por ejemplo, supongamos que creo el siguiente bucle:

procedure TForm1.CrearFactura;
begin
for i := 0 to iLineasDetalle do
ActualizarMovimientosLinea( i );
end;

Vamos hacer que la variable i la declare RAD Studio automáticamente. Hay que seguir estos pasos:

1. Seleccionamos la varible i.

2. La pinchamos con el botón derecho del ratón y seleccionamos Refactoring -> Declare Variable:


Aparecerá esta ventana:


Como puede apreciarse, ya ha reconocido que la variable a declarar es de tipo Integer.

3. Pulsamos el botón Ok y este es el resultado:

procedure TForm1.CrearFactura;
var
i: Integer;
begin
for i := 0 to iLineasDetalle do
ActualizarMovimientosLinea( i );
end;

En procedimientos pequeños como este no suele apreciase mucho esta opción, pero en bloques de código de 50 o 60 líneas si que es un autentico coñazo tener que subir al principio del procedimiento a declarar la variable para luego volver a bajar y seguir por donde íbamos.

Este proceso todavía se puede hacer mucho más rápido si seleccionamos la variable i y luego pulsamos la combinación de teclas Mayúsculas + CTRL + V y luego pulsamos Intro. Cuando te aprendes esta combinación es una auténtica gozada y se gana mucha velocidad.

RENOMBRANDO LAS VARIABLES DE UN BLOQUE DE CÓDIGO

Las opciones de refactorización también permiten renombrar las variables de un bloque de código, ya sea de un procedimiento, función, clase o de toda la unidad.

Muchos os preguntaréis, ¿para que quiero esta opción si ya utilizo CTRL + R para reemplazar trozos de código? Pues con variables que tienen un nombre único no hay problema, pero ¿Qué pasa si necesitas renombrar la variable i de un bucle sin estropear la letra i de todo el resto del código?

Por ejemplo en este bloque de código:

procedure TForm1.Facturar;
var
i: Integer;
begin
for i := 1 to iNumeroPedidos do
FacturarDocumento(i);

for i := 1 to iNumeroAlbaranes do
FacturarDocumento(i);
end;

Si yo intento cambiar el nombre de la variable i por j utilizando CTRL + F me haría este desastre:

procedure TForm1.Facturar;
var
j: jnteger;
begjn
for j := 1 to jNumeroPedjdos do
FacturarDocumento(j);

for j := 1 to jNumeroAlbaranes do
FacturarDocumento(j);
end;

No sólo he ha reemplazado la variable i sino que me ha estropeado dos variables más y hasta el comando begin.

Para hacer esto correctamente hay que seguir estos pasos:

1. Seleccionamos cualquier variable i (ya sea la que está dentro de la sección var o la del bucle).

2. Pulsamos esta variable con el botón derecho del ratón y seleccionamos Refactoring -> Rename variable “i”:


Mostrará este cuadro de diálogo:


3. En el campo New Name podemos j y pulsamos Ok.

4. Como RAD Studio es muy precavido, nos mostrará en la parte inferior de la ventana de código como quedaría el bloque de código después de la operación:


Ahora sólo tenemos que pulsar el botón Refactor y luego cerramos la ventana de refactoring:


Lo bueno que tiene esto es que sólo nos reemplaza la variable dentro de ámbito donde estamos. Si estamos dentro de un procedimiento, sólo nos modifica la variable del mismo y no del resto de la unidad. También detecta cuando estamos renombrando la variable de una clase en concreto o de toda la unidad.

CAMBIANDO LOS PARÁMETROS DE FUNCIONES Y PROCEDIMIENTOS

¿Qué pasa cuando tenemos que añadir, modificar o eliminar un nuevo parámetro a una función o procedimiento de una clase? Hasta ahora teníamos que hacer lo siguiente:

1. Nos vamos a la definición de la clase (dentro de type) y añadimos el nuevo parámetro.

2. Nos vamos a la implementación del procedimiento y también añadimos el nuevo parámetro.

3. Buscamos por todas las unidades del proyecto a ver quien llama a este procedimiento y añadimos el nuevo parámetro (esto lo hacemos compilando y según se vaya quejando el compilador vamos reemplazando código).

Pues ahora sólo tenemos que hacerlo en un solo paso. Por ejemplo tenemos este procedimiento:

procedure TForm1.FacturarDocumento( i: Integer );
begin
MarcarDocumento(i);
CrearFactura;
ActualizarMovimientos;
end;

el cual es llamado por este otro:

procedure TForm1.Facturar;
var
j: integer;
begin
for j := 1 to iNumeroPedidos do
FacturarDocumento(j);

for j := 1 to iNumeroAlbaranes do
FacturarDocumento(j);
end;

Pues bien, supongamos que tengo que añadir otro parámetro:

procedure TForm1.FacturarDocumento( i: Integer; bEstado: Boolean );

Hay que hacerlo del siguiente modo:

1. Selecciono el nombre del procedimiento (FacturarDocumento) con el botón derecho del ratón y selecciono Refactoring -> Change params:


Aparecerá esta ventana:


2. Pulsamos el botón Add y aparecerá este cuadro de diálogo:


3. En el campo Parameter Name escribimos bEstado y en Data type el valor Boolean. Después pulsamos Ok.

3. Volverá a la ventana anterior con el nuevo parámetro:


4. Pulsamos Ok y aparecerá la sección de refactoring informándonos de los las líneas de código afectadas por el cambio:


5. Pulsamos el botón Refactor y trabajo terminado tanto en la declaración de la clase:

private
{ Private declarations }
procedure FacturarDocumento(i: Integer; bEstado: Boolean);
...

Como en la implementación:

procedure TForm1.FacturarDocumento( i: Integer; bEstado: Boolean );
begin
MarcarDocumento(i);
CrearFactura;
ActualizarMovimientos;
end;

Además nos deja preparadas las llamadas este procedimiento para añadir el nuevo parámetro:

procedure TForm1.Facturar;
var
j: integer;
begin
for j := 1 to iNumeroPedidos do
FacturarDocumento(, )(j);

for j := 1 to iNumeroAlbaranes do
FacturarDocumento(, )(j);
end;

Aunque hay que reconocer que esto último es algo rarillo. Pero bueno, al fin y al cabo tenemos que modificar las llamadas y darles el nuevo parámetro. El IDE ha realizado un trabajo limpio e impecable que nos ahorra muchas compilaciones y saltos en el código de allá para acá.

En el próximo artículo seguiremos viendo más novedades.

Pruebas realizadas con RAD Studio 2007.

Publicidad