domingo, 25 de noviembre de 2007

Congreso Virtual de Delphi en Español

Estoy por ser parte de un gran evento para nuestra comunidad latinoamericana de desarrolladores, especialmente (pero en definitiva no exclusivamente) para los que usamos herramientas de CodeGear (from Borland).

CodeGear organiza los Developer Day en Español los días 4 y 5 de diciembre, en donde habrá conferencias, presentaciones y demo en nuestro idioma. Normalmente mencionaría con mucho gusto este efectivo esfuerzo de CodeGear, pero ahora resulta aun mas especial para mi, ya que tendré la responsabilidad (y la fortuna) de exponer, hablarles sobre Generics y formas en que podemos usar y aprovechar esta nueva característica del lenguaje Delphi for .Net. Pero lo mejor es, que dicha característica, los Generics o clases de tipos parametrizados será la siguiente adición al lenguaje Delphi para Win32 nativo (que usamos en mayoría), como lo podemos ver en el RoadMap de Delphi (nombre clave Tiburon).

Aun mejor, existen otras excelentes ponencias:

  • Fabian Duron (nuestro buen FabianDeus del grupo de Programadores Delphi México) nos mostrara las nuevas caracteristicas del IDE en RAD Studio 2007
  • Norberto Martinez (de Gopac y antes de Smartware) hablara sobre algo que es extremo importante para competir: la calidad de las aplicaciones Delphi
  • Andreano Lanusse (CodeGear) expondrá sobre desarrollo de aplicaciones ASP.NET con AJAX en RAD Studio 2007.
  • Por no mencionar las de nuestros colegas Pablo Soligo de Argentina, José Castillo de Perú, David I y Nick Hodges!

En fin, no tiene caso que sustituya la pagina de CodeGear de REGISTRO para el evento.

lunes, 19 de noviembre de 2007

Llamada dinámica a métodos

No es dinámico como en "dinámico de Bajo nivel" sino llamar métodos por su nombre. La Run-Time Type Information (RTTI) es la forma en que Delphi se vuelve mucho mas poderoso al combinarse con herencia y polimorfismo, sin embargo es el punto ahora, el problema es distinto.

Digamos que queremos hacer un pequeño motor de script (básico para empezar). Podemos guardar las instrucciones del script en un archivo de texto, en un campo de una tabla, etc. Nuestro programa lee esas instrucciones y las va ejecutando una por una, haciendo diversas cosas. ¿Dinámico, no?

Bueno es fácil con Delphi. Los métodos tienen una dirección de memoria donde esta el código (las instrucciones en lenguaje máquina) y una dirección de memoria donde esta los datos (digamos el ambiente del método), en este caso son los datos de la clase a la que el método pertenece.

Ahora, ¿Como guardamos una dirección de memoria en Delphi? Un puntero es un tipo de variable que guarda una dirección de memoria, en dicha dirección puede haber cualquier cosa: una cadena, un numero, un arreglo, o... un método. Como toda clase deriva de la Clase TObject, y dicha clase TObject tiene un método llamado MethodAddress con el que obtenemos el puntero hacia un método que sepamos su nombre, entonces si tenemos una clase llamada MiClase que tiene un método llamado Alerta, obtenemos la dirección de memoria donde esta el código que ejecuta ese método de la siguiente manera:

MiClase.MethodAddress("Alerta");


Para representar un método, Delphi tiene una estructura llamada TMethod. Dicha estructura tiene dos componentes: Code y Data (Código y Datos como lo mencionamos antes). En Code va la dirección de memoria de el método, y en Data guardamos la dirección de memoria de la instancia de la clase (es decir, el objeto) a la cual pertenece el método.

Entonces para llamar ejecutar nuestro Script básico, necesitamos una clase que contenga métodos con el nombre de las instrucciones de nuestro script, y después crear una instancia de esa clase (crear un objeto de esa clase), leer nuestro script y por cada linea del script (una instrucción) crear un TMethod obteniendo el puntero hacia esa función. Lo codifíco aquí en un solo procedimiento por facilidad:

// EjecutaScript con el parámetro del nombre
// del archivo "script"
procedure TMiClase.EjecutaScript(ArchScript: string);
var
p:
procedure of Object; // Un puntero a un metodo
Script: TStringList; // Aqui cargaremos el script
instrucc: string; // para iterar por
// las instrucciones
begin
if FileExists(ArchScript) then
begin
Script :
= TStringList.Create();
try
// Si existe el archivo del script
// Cargamos el script a una lista de strings
Script.LoadFromFile(NombreArchivoScript);
// Por cada instrucción (una linea
// en el archivo):
for instrucc in Script do
begin
// Si la linea no es vacía
if trim(instrucc) <> '' then
begin
// Obtenemos la dirección del método y la
// asignamos al elemento Code de
// p como TMethod
TMethod(p).Code := Self.MethodAddress(instrucc);
// Asignamos el objeto mismo
// como Data del TMethod
TMethod(p).Data := Self;
// Si resulto asignado p (no apunta a nil)
if Assigned(p) then
begin
p();
// Ejecutamos p!!
end;
end;
end;
finally
FreeAndNil(Script);
// liberamos el TStringList
// Como debe de ser :P
end;
end;
end;

Ejemplo: Si tenemos un método llamado Alerta, un BorraCache y un Procesa en la clase TMiClase:

// Actualizado 20/nov/2007 - ver nota al pie
TMiClase = class
...
public
procedure EjecutaScript(ArchScript:
string);
...
published
procedure Alerta;
procedure Procesa;
procedure BorraCache;
...
end;


y nuestro script consiste en un archivo llamado por ejemplo 'haznuevo.txt' que contiene:


alerta
borracache
procesa


al invocar:
var
MiObjeto: TMiClase;
begin
MiObjeto :
= TMiClase.Create;
try
MiObjeto.EjecutaScript(
'haznuevo.txt');
finally
FreeAndNil(MiObjeto);
end;
end;

Entonces se ejecutaran los métodos Alerta, BorraCache y Procesa del Objeto MiObjeto (de clase MiClase :)

También hay forma de pasar parámetros, lo mostrare en un post mas adelante.


Actualización 20/nov/2007: Como bien lo señala Al Gonzalez (¡gracias Al!), el método MethodAddress solo funciona para obtener la dirección de métodos declarados como published!! por lo que declararlos en la sección private no funciona.

miércoles, 14 de noviembre de 2007

Delphi 1!? ok....

Tratando de medir el uso y experiencia en Delphi y sus versiones en nuestra comunidad (la comunidad de programadores a los que nos interesa mejorar) nuestro respetado Al González (que todos conocemos como administrador y principal contribuyente en el grupo Programadores Delphi México) ha abierto recientemente una encuesta sobre la versión (o revisión) del IDE de Delphi que usamos (Delphi 1 o 2 hasta Delphi 2007, no incluye Turbo Pascal - ese es aparte).

La encuesta esta en el sitio de Club Delphi en el siguiente URL:

http://www.clubdelphi.com/foros/showthread.php?t=46171


Si no tienes usuario en Club Delphi puedes ver los resultados de la encuesta hasta ahora y algunos comentarios, para contestarla registrate en el Club (GRATIS Y Definitivamente RECOMENDADO).

Por cierto, yo utilizo felizmente BDS 2006 (y no se que estoy e$$perando para cambiar a RAD Studio 2007) :P