Es posible extender un módulo sin generar una ensalada de código, nombres de procedimientos y variables ?
Si es posible .. pero como ?
Supongamos que un modulo complejo requiere de constantes ampliaciones .. normalmente estas ampliaciones se agregan como metodos del modulo, generando un espacio propio para la descripcion y resolucion de cada nueva funcionalidad agregada.
Por ejemplo, si el modulo es un TDataModule, con varias fuentes de datos, tipicamente requerira para el procesamiento extendido de agregar nuevos metodos y variables de instancia.
Si el modulo de datos implementa el modelo de una Orden Compra, esta podria ser cargada a partir de un Presupuesto. Por lo tanto habria que agregar cierta cantidad de funcionalidad relativa a la carga, como ser
Cargar el Presupuesto
Cargar el Detalle de la Orden de Compra a partir del Presupuesto
Actualizar Totales de la Orden de Compra
Finalizar el proceso
Por supuesto es posible escribir un solo metodo que implemente toda esta funcionalidad. El precio ... una posible ensalada de código, dificil de extender (pero no necesariamente de leer)
Pero normalmente se escribe un metodo de cabecera y sub metodos que implementaran partes especificas de la funcionalidad requerida.
TModuloDeDatos.CargarDePresupuesto(const nPresupuestoPar: Integer);
begin
try
IniciaCargaDePresupuesto(nPresupuestoPar);
CargaPresupuesto;
CargaDetalleDePresupuesto;
RecalculaTotales;
finally
FinalizaCargaDePresupuesto;
end;
end;
Este es el enfoque estructurado clasico, la resolucion de un problema se divide en partes y cada una de estas partes se ataca relativamente por separado.
Sin embargo al implementarse esta solucion dentro de una clase pre-existente, agranda esa clase introduciendo funcionalidad especifica, la que luego en la practica no es tan facil de modificar o extender sin impactar en la clase anfitriona.
A medida que el modelo de datos se extiende introduciendo mas y mas funcionalidad - por ejemplo cargar la Orden de Compra de una Solicitud en vez de un Presupuesto - el modelo como conjunto empieza a volverse cada vez mas confuso y dificil de mantener.
En parte por la dificulta en ir inventando nombres nuevos, y en parte porque la reutilizacion de codigo comun a las distintas funcionalidades empieza a introducir la tendencia a duplicar codigo.
Existe una forma muy poco conocida de estructurar codigo sin introducir nuevos metodos .. o muy poco usada. Es la de las subrutinas. Esta es una funcionalidad basica de Pascal, verdaderamente notable.
Dada un metodo ..
TClase.Metodo
begin
end;
Es posible escribir de manera inmediata lo siguiente:
TClase.Metodo;
procedure Inicio;
begin
end;
procedure Proceso;
begin
end;
procedure Fin;
begin
end;
begin
Inicio;
try
Proceso
finally
Fin;
end;
end;
Mas aun, una subrutina puede anidar sub subrutinas y asi siguiendo ..
TClase.Metodo;
procedure Proceso;
function Detecta: Boolean;
begin
end;
procedure SeteaValores;
begin
end;
begin
with Tabla do
begin
while not Eof do
begin
if Detecta then
SeteaValores;
Next;
end;
end;
end;
begin
end;
Incluso mas !!! .. una subrutina puede ser sobrecargada ! .. O sea:
TClase.Metodo;
procedure Proceso; overload;
begin
end;
procedure Proceso(const nParametro: Integer); overload;
begin
end;
begin
end;
Las subrutinas llevan sus propias variables locales en el stack .. y no se confunden con las variables del mismo nombre de un nivel de anidamiento superior ..
TClase.Metodo(const nI: Integer);
var
nJ: Integer;
procedure Proceso(const nI,nJ: Integer);
begin
// El Parametro nI de Proceso .. no es el Parametro nI de TClase.Metodo
// El Parametro nJ de Proceso ... no es la variable local nJ de TClase.Metodo
end;
begin
end;
De esta forma es posible describir encapsulada y estructuradamente el espacio de un problema sin salir nunca de alcanze de un Metodo de Clase, agregando tantas variables locales y sub rutinas anidades como haga falta para describir adecuadamente el problema en cuestion. Mas aun .. este enfoque no introduce problemas semanticos, ya que los nombres de metodos y variables son estrictamente locales y no se confunden con nombres identicos de metodos y variables en la clase contenedora.
Sin embargo este enfoque muy rapido y practico tiene como inconveniente que si una subrutina de un metodo repite codigo de otra subrutina en otro metodo, estariamos introduciendo codigo repetido.
La solucion obvia, es ... subir el nivel de esa subrutina al de un metodo de la Clase contenedora.
O sea ..
TClase.MetodoUno;
procedure Proceso;
begin
MetodoTres;
end;
begin
end;
TClase.MetodoDos;
procedure Proceso;
begin
MetodoTres;
end;
begin
end;
TClase.MetodoTres;
begin
end;
El TClase.MetodoTres .. es entonces una suerte de recurso compartido hibrido del TClase.MetodoUno y TClase.MetodoDos;
Existe sin embargo un enfoque adicional que permite estructurar, encapsular y especializar el codigo de nueva funcionalidad agregada a una Clase, con un minimo de acople.
Sigue en la Parte II
No hay comentarios:
Publicar un comentario