Sou um programador Delphi Pascal, uso o mais recente Embarcadero delphi XE e gostaria de tirar proveito de padrões de design, como Model view controller e model view view-model.
No entanto, não parece haver muito na web sobre as melhores práticas para fazer isso em pascal. A maioria dos exemplos que posso encontrar está em C # e alguns dos recursos de idioma não estão presentes no pascal, o que significa que talvez seja necessário encontrar maneiras de implementar esses recursos.
Estou tentando adaptar o código deste artigo aqui
Vou listar os problemas que estou enfrentando
- Tipos anuláveis
Pascal não tem tipos anuláveis como o C #, então eu criei os meus.
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;
na seção de implementação
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;
- Obter / definir propriedades
Agora que tenho um tipo anulável, posso criar propriedades anuláveis. No entanto, ele vem com alguns odores de código
por exemplo, se eu criar
TFoo = class
private
function GetBar:TNullable<Integer>;
procedure SetBar(x:TNullable<Integer>);
public
property Bar : TNullable<Integer> read GetBar write SetBar;
na seção de implementação
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;
Isso é bom, mas quando se trata de usar essas propriedades, não posso simplesmente usar
myFoo.Bar.Value: = 1;
Eu tenho que usar
var
myBar : TNullable<Integer>;
begin
myBar.Value := 1;
myFoo.Bar := myBar;
end;
O que é um pouco mais confuso. Suponho que não haja nada que eu possa fazer sobre isso.
- Referências circulares
Eu gosto de separar as aulas em diferentes unidades.
ou seja:
mantendo a interface do usuário separada da lógica de controle e da camada lógica de modelo e dados.
Eu posso ter uma situação em que duas classes podem se referir uma à outra. Embora essa seja uma situação que, na maioria das vezes, eu gostaria de evitar, há ocasiões em que isso é necessário.
por exemplo
unit u_A;
interface
uses
u_B
;
type
TA = class
public
Foo : TB;
end;
implementation
end;
e outra unidade
unit u_B;
interface
uses
u_A
;
type
TB = class
public
Foo : TA;
end;
implementation
end;
Esse código está quebrado porque as duas classes se incluem e isso não pode ser feito em pascal. Este não é um problema no C #. As soluções em que consigo pensar: 1. incluem as duas classes na mesma unidade, embora isso seja um problema se eu não achar que isso se adapte ao design. 2. Crie outra interface pai para B e herda B disso, então isso é contornado. Embora isso seja confuso para uma tarefa tão simples.
- Classes estáticas
Não há classes estáticas no Delphi, elas são úteis para classes de controle.
- Melhores classes de contêineres para usar no Delphi
Atualmente, estou usando TList e TObjectList em Generics.Collections Eles foram introduzidos no Delphi XE. Espero que sejam os melhores para usar, pois o delphi 7 não parecia ter boas opções.
Ainda estou pensando nos manipuladores de eventos e em quaisquer problemas que possam surgir por lá. Talvez haja outras questões em que ainda não pensei.
Obrigado por qualquer conselho.
Respostas:
Você deve procurar no Spring4D, pois ele já contém tipos anuláveis (implementação semelhante à sua com uma sobrecarga extra de operador) e tipos de coleção muito mais poderosos do que aqueles na RTL. Eles também são baseados em interface, o que é muito útil, porque você não precisa se preocupar com o gerenciamento da vida útil, especialmente ao distribuí-los.
Para problemas de referência cruzada, sugiro codificar contra interfaces e usá-las como referência em outra implementação, em vez de duas implementações que se conhecem.
Quanto à parte MVVM, você pode procurar no DSharp, que possui uma primeira versão de uma porta Caliburn Micro para Delphi. É um estágio muito inicial e dificilmente documentado, mas você pode ter algumas idéias de como obter o MVVM no Delphi usando a GUI e a lógica de negócios fracamente acopladas conectadas às ligações de dados. A revista Blaise Pascal tinha dois artigos, se você estiver mais interessado.
PS Acho que você quer dizer que está usando o XE6, pois essa é a versão mais recente.
fonte