miércoles, mayo 09, 2007

Object triggers

Aunque es prematuro, todo sea por concretar un poco la idea:
// Freya

Editor = class
public
property
CurrentPosition: Position;
event PositionChanged: EventHandler;
protected
method
OnPositionChanged; virtual;
begin
var
eh := PositionChanged;
if eh <> nil then
eh(Self, EventArgs.Empty);
end;
implementation
    // Este es un trigger: se admite read, write y execute.
// Pueden combinarse varios recursos en un mismo trigger.

on CurrentPosition(write)
var
// Estas variables se convierten en campos
flag: Integer := 0;
begin
flag++;
// Esto sí es una verdadera variable local:
var initialPosition := currentPosition;
finally
flag--;
if flag = 0 then
if initialPosition <> currentPosition then
OnPositionChanged;
end;
end;
A trigger, what else?He intentado no meter palabras reservadas nuevas, al menos mientras no estén más claras las ideas. Lo que quiero averiguar es si con esta simple técnica se pueden lograr todas las cosas positivas de la AOP, sin provocar, a la misma vez, todos los problemas que ahora provoca. La clase, por supuesto, tendría mucho más código, y los triggers, por llamarlos de algún modo, siempre van en la implementación de la clase (no interesan al cliente de la clase).
Importante: los campos usados por un trigger son solamente visibles para el propio trigger. Por ello puede usarse un nombre como flag sin preocupaciones, porque de existir ya un miembro con este nombre, el campo se renombraría.
Y por supuesto, la historia puede complicarse todo lo que se quiera: ¿se podrían heredar triggers para aplicarse a nuevos recursos? Probablemente sí, en la medida en que el recurso protegido pueda ser modificado en una clase derivada. ¿Tiene sentido definir triggers independientemente del recurso que protegen, para enlazarlos luego con un recurso en una implementación? Supongo que dependerá de la complejidad del código que pueda meterse en un trigger.
Observe también que, en general, podría vigilarse más de un recurso con el mismo trigger. Imagine que, en vez de tener una variable (o una propiedad) que encapsula fila y columna, tenemos dos campos separados. En tal caso, el mismo trigger se "tejería" para los métodos que modificasen uno u otro campo. ¿Tiene sentido definir triggers para que se apliquen cuando un método acceda a uno y otro campo? No lo sé: tengo que encontrar un ejemplo con sentido. De esto, de encontrar más ejemplos, se trata ahora.

NOTAS
A quien haya seguido ejemplos anteriores en Freya, le extrañará probablemente la implementación en línea del método OnPositionChanged. No hay nada extraño: Freya sigue manteniendo el viejo formato, con las declaraciones en secciones public/private y secciones implementation for para las implementaciones. Pero ahora también es posible utilizar el estilo en línea, como en Eiffel (y Java y C#). Observe, de paso, que incluso en tal caso sigue existiendo una sección implementation, aunque en ella ya no se menciona la clase, por ser innecesario. En esta sección siguen residiendo los "detalles de implementación", que sería inapropiado situar en una sección "regular". Por ejemplo: constructores de clase (estáticos), delegaciones de implementación para tipos de interfaz, implementaciones explícitas de miembros de interfaces y destructores.
Una vez aclarado este punto, observe que CurrentPosition es una propiedad sin implementación explícita. En estos casos, el compilador declara un identificador oculto y genera automáticamente los métodos de acceso necesarios. Mejor aún: cuando se hace referencia a la propiedad dentro de la misma clase, ésta se sustituye por una referencia al campo. Y si la propiedad no es virtual, el campo oculto se declara internal, y la optimización se realiza también para los usos de la propiedad dentro del propio ensamblado, con independencia de la clase. Si alguna vez se cuestiona la necesidad de Freya, recuerde que la calidad del código generado es muy superior a la media de los compiladores para .NET, a pesar de las limitaciones impuestas por la plataforma :)
Otro pequeño detalle: observo cómo copio el valor del evento PositionChanged antes de comprobar su valor y ejecutarlo. Es común ver por ahí código que no utiliza una variable temporal, pero aunque teóricamente es correcto, podemos tener problema si alguna vez accedemos al mismo objeto desde dos hilos paralelos. La técnica mostrada es la "correcta", teniendo en cuenta esta posibilidad.

Etiquetas: , ,

4 Comments:

Anonymous Anónimo said...

Hola, disculpa el cambio de tema pero no esta accesible http://www.classiqueCentral.com/

jueves, mayo 10, 2007 7:03:00 p. m.  
Blogger Ian Marteens said...

Parece un problema de DNS: es un servidor interno registrado con una empresa externa. Estoy en ello. Si no logro arreglarlo esta mañana, te envío por email lo que te falte por descargar.

viernes, mayo 11, 2007 10:26:00 a. m.  
Blogger MrDomino said...

Hola Ian,
Nada que ver con este Tema, pero que pasa con el sitio "classiquecentral.com" dice que el servicio a expirado.

martes, mayo 22, 2007 4:24:00 p. m.  
Blogger Unknown said...

Hola, hoy 11 agosto 2008 acabo de ingresar por primera vez al sitio "classiquecentral.com" y me aparece innaccesible, alguien me puede ayudar a ingresar?

SALUDOS

lunes, agosto 11, 2008 5:40:00 p. m.  

Publicar un comentario

<< Home