Soy un programador pascal de Delphi, utilizo el último Embarcadero delphi XE, y me gustaría aprovechar los patrones de diseño como el controlador de vista de modelo y la vista de modelo.
Sin embargo, no parece haber mucho en la web sobre las mejores prácticas para hacer esto en pascal. La mayoría de los ejemplos que puedo encontrar están en C # y algunas de las características del lenguaje no están presentes en pascal, lo que significa que quizás tenga que encontrar formas de implementar esas características.
Estoy tratando de adaptar el código de este artículo aquí.
Voy a enumerar los problemas que estoy enfrentando
- Tipos anulables
Pascal no tiene tipos anulables como C #, así que he creado el mío.
TNullable<T> = record
strict private
fHasValue : boolean;
fValue : T;
function GetValue:T;
procedure SetValue(newValue : T);
public
property HasValue : boolean read fHasValue;
property Value : T read GetValue write SetValue;
procedure SetToNull;
end;
en la sección de implementación
function TNullable<T>.GetValue:T;
begin
if fHasValue then
begin
Result := fValue;
end
else raise Exception.Create('Value Not Set');
end;
procedure TNullable<T>.SetValue(newValue : T);
begin
fValue := newValue;
fHasValue := true;
end;
procedure TNullable<T>.SetToNull;
begin
fHasValue := false;
end;
- Obtener / Establecer para propiedades
Ahora que tengo un tipo anulable, puedo crear propiedades anulables. Sin embargo, viene con algunos olores de código
por ejemplo si creo
TFoo = class
private
function GetBar:TNullable<Integer>;
procedure SetBar(x:TNullable<Integer>);
public
property Bar : TNullable<Integer> read GetBar write SetBar;
en la sección de implementación
function TFoo.GetBar:TNullable<Integer>;
begin
if **valueExists** then
begin
Result.Value := **the value**
end else
begin
Result.SetToNull;
end;
end;
procedure TFoo.SetBar(x:TNullable<Integer>);
begin
if X.hasValue then
begin
//Store/show value here
end else
begin
//handle null assignment here
end;
end;
Esto está bien, pero cuando se trata de usar estas propiedades, no puedo simplemente usar
myFoo.Bar.Value: = 1;
Tengo que usar
var
myBar : TNullable<Integer>;
begin
myBar.Value := 1;
myFoo.Bar := myBar;
end;
Lo cual es un poco más desordenado. Supongo que no hay nada que pueda hacer al respecto.
- Referencias circulares
Me gusta separar las clases en diferentes unidades.
es decir:
manteniendo la interfaz de usuario separada de la lógica de control y el modelo y la capa de lógica de datos.
Puedo tener una situación en la que 2 clases pueden referenciarse entre sí. Si bien esta es una situación que en su mayor parte me gustaría evitar, hay ocasiones en que esto es necesario.
por ejemplo
unit u_A;
interface
uses
u_B
;
type
TA = class
public
Foo : TB;
end;
implementation
end;
y otra unidad
unit u_B;
interface
uses
u_A
;
type
TB = class
public
Foo : TA;
end;
implementation
end;
Este código está roto porque las dos clases se incluyen entre sí y esto no se puede hacer en pascal. Esto no es un problema en C #. Soluciones en las que puedo pensar: 1. incluir ambas clases en la misma unidad, aunque esto es un problema si no creo que esto se adapte al diseño. 2. Cree otra interfaz principal para B y herede B de eso, entonces esto lo evita. Aunque esto es complicado para una tarea tan simple.
- Clases estáticas
No hay clases estáticas en Delphi, estas son útiles para las clases de control.
- Las mejores clases de contenedores para usar en Delphi
Actualmente estoy usando TList y TObjectList en genéricos. Colecciones Se introdujeron en Delphi XE. Espero que sean las mejores para usar, ya que delphi 7 no parecía tener buenas opciones.
Todavía estoy pensando en los controladores de eventos y cualquier problema que pueda surgir allí. Quizás hay otros problemas que aún no he pensado.
Gracias por cualquier consejo
Respuestas:
Debería examinar Spring4D ya que ya contiene tipos anulables (implementación similar a la suya con una pequeña sobrecarga adicional del operador) y tipos de colección mucho más potentes que los de RTL. También están basados en interfaces, lo cual es muy útil porque no tiene que preocuparse por la administración de por vida, especialmente al pasarlos.
Para problemas de referencias cruzadas, sugiero la codificación contra interfaces y usarlas como referencia en otra implementación en lugar de que 2 implementaciones se conozcan entre sí.
En cuanto a la parte MVVM, puede buscar en DSharp, que tiene una primera versión de un puerto Caliburn Micro para Delphi. Es una etapa muy temprana y apenas documentada, pero puede obtener algunas ideas sobre cómo lograr MVVM en Delphi utilizando una GUI débilmente acoplada y una lógica empresarial conectada con enlaces de datos. La revista Blaise Pascal tenía dos artículos al respecto si está más interesado.
PD: Supongo que te refieres a que estás usando XE6, ya que es la última versión.
fuente