Gráfciamente MVC puede entender asi:
Como sería la implementación concreta en Delphi de este principio ?
Muy simple:
TVista.BotonOnClick(Sender: TObject);
begin
TModelo.Proceso;
end;
TModelo.Proceso;
begin
.
.
end;
Notemos que en este ejemplo no hay una clase Controladora .. porque ? .. porque en realidad el Modelo relacional se comunica con las Vista a través las fuentes de datos (clase TDataSource)
TModelo.Proceso;
begin
with TablaCliente do
begin
DisableControls;
try
First;
while not Eof do
begin
.
.
Next;
end;
finally
EnableControls;
end;
end;
Todo programador Delphi conoce esto. El método DisableControls de un descendiente de la clase TDataSet .. en relacion a MVC, desconecta el Modelo de la Vista .. a la manera Delphi.
Inversamente EnableControls, reconecta la Vista con el Modelo, actualizándola segun el estado del TDataSet a ese momento.
De nuevo .. 'donde estan los controladores ?' .. Los controladores existen dentro de los controles de tipo 'data-aware' y 'saben' como refrescar sus vistas.
O sea, para dar un ejemplo .. el componente TDbEdit, tiene una parte de Vista (la que se ve y se dibuja en el Form que lo contiene) y otra parte de Controlador.
Tecnicas en Delphi
Mis ideas acerca de como encarar situaciones de diseño .. usando Delphi !
Translate
martes, 26 de junio de 2012
lunes, 25 de junio de 2012
Es Delphi MVC ? ... Parte III
De como Delphi naturalmente permite implementar MVC .. en buena medida ..
Ya vimos que la pregunta correcta no es si Delphi es o no MVC .. sino si Delphi permite implementar el principio MVC (para algunos quizás solamente 'patrón')
Implementaciones de MVC, hay muchísimas .. pero todas usan el patrón de diseño llamado 'El Observador' ..
Este es un patrón muy conocido y usado. Básicamente consiste en que 'algo' al cambiar, le comunica que cambió a un conjunto de 'observadores' que actuarán en consecuencia, haciendo 'algo', eventualmente nada.
Ya lo dice Wikipedia:
Es un patrón de diseño que define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, notifica este cambio a todos los dependientes.
Y cual sería la 'cosa' que cambia y cuyos cambios deben ser 'observados' ? .. la respuesta es obvia: El Modelo.
Ahora llegamos a un punto crucial .. como permite representar Delphi a un 'Modelo' ?? .. La respuesta es:
Ya vimos que la pregunta correcta no es si Delphi es o no MVC .. sino si Delphi permite implementar el principio MVC (para algunos quizás solamente 'patrón')
Implementaciones de MVC, hay muchísimas .. pero todas usan el patrón de diseño llamado 'El Observador' ..
Este es un patrón muy conocido y usado. Básicamente consiste en que 'algo' al cambiar, le comunica que cambió a un conjunto de 'observadores' que actuarán en consecuencia, haciendo 'algo', eventualmente nada.
Ya lo dice Wikipedia:
Es un patrón de diseño que define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, notifica este cambio a todos los dependientes.
Y cual sería la 'cosa' que cambia y cuyos cambios deben ser 'observados' ? .. la respuesta es obvia: El Modelo.
Ahora llegamos a un punto crucial .. como permite representar Delphi a un 'Modelo' ?? .. La respuesta es:
- Delphi permite representar un Modelo como mejor a uno la parezca, porque es un compilador potentisimo y muy sofisticado
- La manera obvia de representar un Modelo es con Clases y propiedades .. esto es bastante claro. Acá habrá que resolver la 'persistencia' del Modelo.
- Delphi, sin embargo estar orientado naturalmente a un Modelo 'relacional' .. o sea basado en Tablas y columnas.
Es tan fuerte la implementacion del 'modelo relacional' en Delphi .. tan madura, sofisticada y versátil .. que justamente da lugar a la experiencia RAD que en mi opinión es algo único, distintivo de Delphi.
O sea la posiblidad de diseñar un modelo de tipo relacional y .. precisamente conectarlo a las Vistas de manera inmediata.
A esta altura ya todos sabemos de que estoy hablando .. el patrón del 'Observador' esta naturalmente implementado en Delphi a traves de la conexion entre descendientes del componente TDataSet y el componente TDataSource .. el que a su vez conecta naturalmente con las Vistas .. las que responden automáticamente a cualquier cambio que se produce en el Modelo (relacional)
Que es lo que ocurre cuando un programador que no sabe de MVC, empieza a escribir código en Delphi ??
Pues que 'mezcla' .. todo en una sola unidad descendiente de TForm .. usualmente. Entonces el Modelo la Vista y los Controladores .. colusionan en un mismo espacio entremezclados y vuelven dificil el mantenimiento y la extensión.
Es esto culpa de Delphi ?? .. pues si y no.
Y entonces como se controla una aplicacion ? .. Esto la sabe cualquier programador de Delphi !!! .. escribiendo código en los Eventos de los 'Controles' que están sobre las Vistas ..
De hecho, ese código de control de la aplicacion hace las dos cosas esperadas de un controlador:
Que es lo que ocurre cuando un programador que no sabe de MVC, empieza a escribir código en Delphi ??
Pues que 'mezcla' .. todo en una sola unidad descendiente de TForm .. usualmente. Entonces el Modelo la Vista y los Controladores .. colusionan en un mismo espacio entremezclados y vuelven dificil el mantenimiento y la extensión.
Es esto culpa de Delphi ?? .. pues si y no.
- Si .. porque Delphi permite escribir tan pero tan facil todo junto que pocos se toman el trabajo de separar el código del Modelo del código de las Vistas ..
- No .. porque, Delphi propone desde hace mucho tiempo escribir el código de 'datos' (el Modelo relacional) en la clase TDataModule, diseñada específicamente para colocar el código relacional (Componentes, Métodos, Interfases .. etc)
Y entonces como se controla una aplicacion ? .. Esto la sabe cualquier programador de Delphi !!! .. escribiendo código en los Eventos de los 'Controles' que están sobre las Vistas ..
De hecho, ese código de control de la aplicacion hace las dos cosas esperadas de un controlador:
- Ejecuta métodos del Modelo (Ejemplo: El Operador presiona un botón de 'Grabar' y el controlador ejecuta el método .. Modelo.GrabarDatos())
- Y eventualmente acciona sobre la Vista misma (Ejemplo: El Operador presiona un ToolButton y deshabilita otros o cambia en algo la apariencia de la Vista, ocultando o mostrando controles)
Finalmente no deja de ser importante notar que los controles del tipo 'Data aware' .. o sea conectados a una Fuente (a través en realidad del objeto interno TDataSetLink) ... tienen su propio Controlador interno.
viernes, 22 de junio de 2012
Es Delphi MVC ? .. Parte II
Mas sobre MVC
En la primer parte, hemos visto que MVC es un 'patron' de diseño. Realmente es una gran abstracción que de manera muy general enmarca el diseño de cualquier aplicación, sea esta del tipo que sea.
Por lo tanto MVC es una suerte de principio general de diseño. Independientemente de la aplicación es posible verificar que:
En la primer parte, hemos visto que MVC es un 'patron' de diseño. Realmente es una gran abstracción que de manera muy general enmarca el diseño de cualquier aplicación, sea esta del tipo que sea.
Por lo tanto MVC es una suerte de principio general de diseño. Independientemente de la aplicación es posible verificar que:
- Siempre existe la 'cosa' sobre la que se construye una o mas aplicaciones .. sea esta una Empresa, Red Social, Persona, Institucion, Objeto ... A la abstracción de esta 'cosa' la llamamos Modelo.
- Existen infinitas formas de 'ver' el Modelo .. pantallas, reportes, graficos. A estas formas se les da el nombre genérico de Vistas.
Es completamente claro que los cambios en la estructura del Modelo, usualmente impactarán sobre las Vistas.
Por ejemplo si agregamos un nuevo dato al Modelo, algunas Vistas pre-existentes deberán ser modificadas para reflejar este cambio. Lo mismo si son modificados o elminados datos del Modelo.
Notablemente los cambios en la funcionalidad del Modelo .. en principio no afectará a las Vistas. Por ejemplo, es posible cambiar una regla de cálculo sin que haya que tocar una sola Pantalla. Lo mismo ocurre con las validaciones .. lo mismo con procesos internos que no tienen reflejo alguno en las Vistas.
En cuanto a las Vistas, la situacion es mas simple. Esta claro que en principio ningun cambio en ellas debiera impactar el Modelo en ningun sentido.De hecho .. una Vista puede desaparecer sin que al Modelo le impacte en nada.
Por lo tanto Modelo y Vistas se hallan en una relación estructural del tipo uno a muchos, con un tipo de acople unidireccional y de baja intensidad.
Sintetizando ..
- Hay un Modelo y cero, una o mas vistas que dependen de este.
- Los cambios en la estructura del Modelo, afectan en general a algunas Vistas.
- Los cambios funcionales en el Modelo, en general no afectan a ninguna Vistas.
- Los cambios en las Vistas no afectan al Modelo.
Lo notable es que una aplicación, surge de la unión entre el Modelo y las Vistas a través de los Controladores, permitiendo la interacción del Operador y otros tipos de interacciones mas o menos automáticas.
En ese sentido los controladores serian el codigo 'específico' que no es del Modelo y que hacen funcionar a cada Aplicacion. Y esto tambien es una importante abstracción.
Suficiente de MVC !! .. vamos ahora a ver como Delphi en mi opinión permite programar según este principio general.
Sigue en la Parte III
En ese sentido los controladores serian el codigo 'específico' que no es del Modelo y que hacen funcionar a cada Aplicacion. Y esto tambien es una importante abstracción.
Suficiente de MVC !! .. vamos ahora a ver como Delphi en mi opinión permite programar según este principio general.
Sigue en la Parte III
Es Delphi MVC ? .. Parte I
Es Delphi MVC ? .. o no lo es ? .. Pero ante todo, que es MVC ?
MVC es un patron de diseño, basado en una abstraccion que describe las tres partes que (segun esta abstraccion) constituyen un Sistema y la forma en que interactuan entre si.
Estas partes son el Modelo, las Vistas y los Controladores. Y es facil de entender .. una vez que se comprende que MVC es una abstraccion y no una implementacion concreta.
Que es el Modelo ? .. es la representacion abstracta de 'algo' (tipicamente una Empresa) con sus objetos, reglas, conceptos, etc .. (Clientes, Proveedores, Comprobantes, Politicas de Precios, etc) .. pero no necesariamente una Empresa, puede ser cualquier otra cosa 'viva' ..
Que son las Vistas ? .. simplemente las distintas representaciones mas o menos complejas de aspectos de un Modelo. Pueden ser Consultas, Graficos, Formularios, Reportes, etc ..
Que son los Controladores ? .. son mecanismos construidos especificamente para que las Vistas y el Modelo interactuen con o sin la presencia de un Operador. A estos controladores los llamamos 'codigo' .. 'logica de control' .. 'manejadores de eventos' ..
Es importante entender a continuacion lo siguiente:
El Modelo puede existir, como representacion abstracta de 'algo' sin que haya una vista y mucho menos controladores. O sea .. el modelo de una Empresa puede existir sin que jamas se construya una (o mas de una) aplicación con sus Pantallas, Reportes, etc.
Las Vistas se construyen y agregan segun deseo o conveniencia y el que una Vista cambie, no cambia en nada al Modelo. Por ejemplo en vez de mostrar datos en formato de registro pasa a mostrarlos en formato tabular .. o se muestran mas datos .. o simplemente cambia el color de fondo del Formulario .. cambia la Vista, pero no el Modelo.
Los controladores permiten la interaccion concreta entres las Vistas y el Modelo .. en un ida y vuelta .. Si 'algo' ocurre en una Vista que requiere de codigo de control - por ejemplo el Operador presiona el boton 'Okey' - .. se ejecutara ese codigo de control que accionara sobre el Modelo (por ejemplo mandando los datos de la Vista para que sean grabados y de esa forma alterando el Modelo) .. y al reves .. si 'algo' ocurre en el Modelo, a traves de un mecanismo de transmision este le informara a cada uno de los Controladores los que a su vez accionaran sobres las Vistas para que ajusten su representacion del Modelo (por ejemplo cambian datos en el Modelo que deben ser resfrescados en las distintas Vistas que representan esos datos)
Simplemente que el Modelo y las Vistas deben existir separadamente - lo mas separadamente posible - de forma tal que un cambio en el diseño del Modelo impacte lo minimo posible en las Vistas y al reves .. un cambio en cualquiera de las Vistas no cambie en nada al Modelo.
Ademas que el diseño general permita la interaccion entre el Modelo y las Vistas .. a traves de los Controladores. Como se dijo antes .. los cambios en el Modelo llegan a las Vista a traves de los Controladores y los cambios en las Vistas llegan al Modelo tambien a traves de estos.
Que tiene que ver Delphi con todo esto ? .. pues nada .. Delphi es un marco de desarrollo de aplicaciones que permite o no implementar el patron MVC con mayor o menor facilidad que otros entornos de programacion.
En la segunda parte de este artículo veremos como en realidad .. Dephi permite implementar en gran parte este patron de manera casi natural.
Otra forma de escribir SQL
Es muy comun ver Sql embebido en codigo de la siguiente forma:
sql:=
'select cmp.fecha,cmp.cliente from comprobantes cmp left join movimientos mov '+
'on nmov.comprobante=cmp.comprobante left join clientes cli on cli.cliente=cmp.cliente '+
'left join articulos art on art.articulo=mov.articulo left join comprobantesimpuestos cim on '+
'cim.comprobante=cmp.comprobante '+
'where cmp.fecha between '+QuotedStr(datetostr(fechadesde))+' and '+QuotedStr(datetostr(fechahasta))+' and '+
'cli.cliente='+inttostr(cliente)
Los dos problemas que presenta esta forma de embeber sql en codigo, aparte de lo puramente estetico, son:
Es dificil de leer el sql .. o sea entender que hace.
La asignacion de valores de parametros exige la conversion en cada caso y es facil equivocarse. Por ejemplo las fechas deben ser convertidas y colocadas entre comillas.
Es posible escribir SQL embebido de una manera mejor ?
Si .. pero como ?
Una vez un gran programador me djo .. 'no te preocupes por el como sino por el que'
Por lo tanto empezemos por el 'que'. Imaginemos una clase que se dedique a construir un texto SQL ..
with TTextoDeSql.Create([
'SELECT',
'CMP.FECHA,',
'CMP.CLIENTE',
'FROM',
'COMPROBANTES CMP',
'LEFT JOIN',
'MOVIMIENTOS MOV ON MOV.COMPROBANTE=CMP.COMPROBANTE',
'LEFT JOIN',
'CLIENTES CLI ON CLI.CLIENTE=CMP.CLIENTE',
'LEFT JOIN',
'ARTICULOS ART ON ART.ARTICULO=MOV.ARTICULO',
'LEFT JOIN',
'COMPROBANTESIMPUESTOS CIM ON CIM.COMPROBANTE=CMP.COMPROBANTE',
'WHERE',
'CMP.FECHA BETWEEN @DESDE AND @HASTA AND',
'CMP.CLIENTE=@CLIENTE ']) do
try
Parametro('DESDE',dFechaDesde);
Parametro('HASTA',dFechaHasta);
Parametro('CLIENTE',nCliente);
Result:=Texto;
finally
Free;
end;
Es mas legible no ? ... No solo eso, la clase TTextoDeSql, se ocupara de transforma los valores asignados a los distintos parametros en literales validos para una sentencia SQL, sin que hay que preocuparse por comillas, conversiones, concatencion y demas.
Clases colaborativas en Delphi. Parte II
En el artículo anterior revisabamos las formas de agregar nueva funcionalidad a una Clase, intentando mantener el codigo lo mas ordenado posible ..
En la practica esto es mas dificil de lo que parece y cualquier programador sabe que al cabo de algunas extensiones el codigo original, se transforma en una secuencia de codigo, dificil de leer y fundamentalmente dificil de extender o modificar.
Las tres formas explicadas anteriormente son:
La programacion lineal
Es simplemente escribir en un solo metodo todo la funcionalidad, lo que resulta naturalmente en un codigo absolutamente no reusable.
Pero la programacion lineal tiene en general una ventaja indudable .. es muy facil de leer !! .. porque el flujo procede de la primer linea a la ultima una despues de otra.
Este modo a pesar de ser tabu .. es de hecho utilizado por miles de programadores que simplemente no quieren tomarse la molestia de estructurar codigo.
La programacion estructurada
Simplemente, consiste en dividir un problema en partes e implementar cada parte en un nuevo metodo. De esta forma es posible identificar mejor las parte de un problema y eventualmente reusar aquellas que deban ser utlizadas en distintos contextos.
La programacion estructurada con sub rutinas
Similar a la anterior, pero las partes de un problema quedan estructuradas como sub rutinas de un metodo. En ese sentido, el metodo incluye todos los recursos necesarios para su implementacion: subrutinas, sub subrutinas (etc),
variables locales, sobrecarga .. y hasta recursividad ! (ver Clases Colaborativas Parte I)
Las clases colaborativas
Este enfoque no tiene nada de 'nuevo' .. tan solo que es muy poco usado. Consiste en la creacion de clases que se dedican a resolver problemas especificos. A la clase asi dedicada, no le 'importa' nada mas que el problema que tiene que resolver.
Todo el espacio de esta clase, esta precisamente dedicado a resolver el problema, incluyendo sus metodos y variables de instancia.
Si dos problemas se parecen, las soluciones pueden derivarse de clases colaborativas basicas o abstractas, que sientan las base de resolucion de un problema, en general.
La implementacion de estas clases, es sorprendetemente simple y promueve la resolucion ordenada de problemas o aspectos de una clase superior.
Por ejemplo:
TClase = class
public
procedure ProblemaUno;
end;
TClaseColaborativa = class;
TTipoDeClaseColaborativa = class of TClaseColaborativa;
TClaseColaborativa = class
private
oClase: TClase;
protected
procedure Inicio; virtual;
procedure Proceso; virtual;
procedure Fin; virtual;
class function TipoDeClase: TTipoDeClaseColaborativa; virtual; abstract;
public
constructor Create(const oClasePar: TClase);
procedure Resuelve; overload;
class procedure Resuelve(const oClasePar: TClase); overload;
end;
TResuelveProblemaUno = class(TClaseColaborativa )
protected
class function TipoDeClase: TTipoDeClaseColaborativa; override;
end;
TResuelveProblemaDos = class(TClaseColaborativa)
protected
class function TipoDeClase: TTipoDeClaseColaborativa; override;
end;
implementation
{ TClase }
TClase.ProblemaUno;
begin
TResuelveProblemaUno.Resuelve(Self);
end;
{ TClaseColaborativa }
TClaseColaborativa.Create(const oClasePar: TClase)
begin
inherited Create;
oClase:=oClasePar;
end;
TClaseColaborativa.Resuelve(const oClasePar: TClase);
begin
with TipoDeClase.Create(oClasePar) do
try
Resuelve;
finally
Free;
end;
end;
TClaseColaborativa.Resuelve;
begin
Inicio;
try
Proceso;
finally
Fin;
end;
end;
TClaseColaborativa.Inicio;
begin
end;
TClaseColaborativa.Proceso;
begin
end;
TClaseColaborativa.Fin;
begin
end;
{ TResuelveProblemaUno }
TResuelveProblemaUno.TipoDeClase; override;
begin
Result:=TResuelveProblemaUno;
end;
{ TResuelveProblemaDos }
TResuelveProblemaDos.TipoDeClase; override;
begin
Result:=TResuelveProblemaDos;
end;
Lo importante aqui son dos cosas ...
TClase.ProblemaUno;
begin
TResuelveProblemaUno.Resuelve(Self);
end;
La implementacion del ProblemaUno .. queda a cargo de la clase dedicada que es TResuelveProblemaUno, a traves del metodo de clase Resuelve. Y ademas ..
TClaseColaborativa = class
.
.
end;
Esta es un clase basica que presta el marco general para las clases resolvedoras de problemas especificos que seran heredadas de esta misma.
Clases colaborativas en Delphi. Parte I
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
Suscribirse a:
Entradas (Atom)