Najlepsze praktyki wdrażania MVVM i MVC w delphi Pascal


10

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: Struktura

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.


Pierwotnie zadałem to pytanie podczas przeglądu kodu, ale zasugerowano, żebym opublikował tutaj.
sav

Odpowiedzi:


9

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.