Jestem programistą Delphi pascal, używam najnowszej wersji Embarcadero delphi XE i chciałbym skorzystać z wzorców projektowych, takich jak kontroler widoku modelu i widok modelu.
Jednak wydaje się, że w Internecie nie ma zbyt wiele na temat najlepszych praktyk wykonywania tego w pascal. Większość przykładów, które mogę znaleźć, są w języku C #, a niektóre funkcje językowe nie są dostępne w języku pascal, co oznacza, że być może będę musiał znaleźć sposoby na wdrożenie tych funkcji.
Próbuję dostosować kod z tego artykułu tutaj
Wymienię problemy, które napotykam
- Typy zerowalne
Pascal nie ma typów zerowalnych jak C #, więc utworzyłem własne.
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;
w dziale implementacji
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;
- Uzyskaj / ustaw właściwości
Teraz, gdy mam typ zerowalny, mogę tworzyć właściwości zerowalne. Jednak zawiera pewne zapachy kodowe
na przykład, jeśli utworzę
TFoo = class
private
function GetBar:TNullable<Integer>;
procedure SetBar(x:TNullable<Integer>);
public
property Bar : TNullable<Integer> read GetBar write SetBar;
w dziale implementacji
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;
To dobrze, ale jeśli chodzi o użycie tych właściwości, nie mogę po prostu użyć
myFoo.Bar.Value: = 1;
Muszę użyć
var
myBar : TNullable<Integer>;
begin
myBar.Value := 1;
myFoo.Bar := myBar;
end;
Co jest nieco bardziej nieporządne. Podejrzewam, że nic nie mogę na to poradzić.
- Referencje okólne
Lubię rozdzielać klasy na różne jednostki.
to znaczy:
oddzielenie interfejsu użytkownika od logiki sterowania oraz warstwy modelu i logiki danych.
Mogę mieć sytuację, w której 2 klasy mogą się nawzajem odnosić. Chociaż w większości przypadków chciałbym tego uniknąć, są sytuacje, w których jest to potrzebne.
na przykład
unit u_A;
interface
uses
u_B
;
type
TA = class
public
Foo : TB;
end;
implementation
end;
i inna jednostka
unit u_B;
interface
uses
u_A
;
type
TB = class
public
Foo : TA;
end;
implementation
end;
Ten kod jest zepsuty, ponieważ obie klasy obejmują się nawzajem i nie można tego zrobić w pascal. To nie jest taki problem w C #. Rozwiązania, które mogę wymyślić: 1. obejmują obie klasy w tej samej jednostce, chociaż jest to problem, jeśli nie uważam, że to pasuje do projektu. 2. Utwórz kolejny interfejs nadrzędny dla B i odziedzicz z niego B, a następnie to obejdzie. Chociaż jest to bałagan w przypadku tak prostego zadania.
- Klasy statyczne
W Delphi nie ma żadnych klas statycznych, są one przydatne dla klas kontrolnych.
- Najlepsze klasy kontenerów do użycia w Delphi
Obecnie używam TList i TObjectList w Generics.Collections Zostały one wprowadzone w Delphi XE Mam nadzieję, że są one najlepsze w użyciu, ponieważ delphi 7 nie miał dobrych opcji.
Nadal myślę o procedurach obsługi zdarzeń i wszelkich problemach, które mogą się tam pojawić. Być może są jeszcze inne kwestie, o których jeszcze nie myślałem.
Dziękuję za wszelkie porady.
Odpowiedzi:
Powinieneś spojrzeć na Spring4D, ponieważ zawiera on już typy zerowalne (podobna implementacja jak twoja z niewielkim dodatkowym przeciążeniem operatora) i znacznie potężniejsze typy kolekcji niż te w RTL. Są one również oparte na interfejsie, co jest bardzo przydatne, ponieważ nie musisz martwić się o zarządzanie przez całe życie, szczególnie podczas ich przekazywania.
W przypadku problemów z odsyłaczami sugeruję kodowanie interfejsów i używanie ich jako odniesienia w innej implementacji zamiast w dwóch implementacjach, które się znają.
Jeśli chodzi o część MVVM, możesz zajrzeć do DSharp, który ma pierwszą wersję portu Caliburn Micro dla Delphi. Jest to bardzo wczesny etap i mało udokumentowany, ale możesz mieć pewne pomysły, jak osiągnąć MVVM w Delphi przy użyciu luźno sprzężonego GUI i logiki biznesowej związanej z powiązaniami danych. Magazyn Blaise Pascal miał dwa artykuły na ten temat, jeśli jesteś bardziej zainteresowany.
PS Chyba masz na myśli, że używasz XE6, ponieważ jest to najnowsza wersja.
źródło