Best practice per l'implementazione di MVVM e MVC in delphi Pascal

9

Sono un programmatore pascal di Delphi, utilizzo l'ultimo Embarcadero delphi XE e mi piacerebbe approfittare di schemi di progettazione come Model View Controller e Model View Model.

Tuttavia, non sembra che ci sia molto sul web riguardo alle migliori pratiche per farlo in Pascal. La maggior parte degli esempi che riesco a trovare sono in C # e alcune funzionalità del linguaggio non sono presenti in pascal, il che significa che potrei dover trovare dei modi per implementare queste funzionalità.

Sto cercando di adattare il codice di questo articolo qui

Elencherò i problemi che sto affrontando

  • Tipi Nullable

Pascal non ha tipi nullable come C #, quindi ho creato il mio.

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;

nella sezione implementazione

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;
  • Ottieni / Imposta proprietà

Ora che ho un tipo nullable posso creare proprietà nullable Tuttavia viene fornito con alcuni odori di codice

per esempio se creo

    TFoo = class
      private
        function GetBar:TNullable<Integer>;
        procedure SetBar(x:TNullable<Integer>);
      public 
        property Bar : TNullable<Integer> read GetBar write SetBar;

nella sezione implementazione

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;

Questo va bene, ma quando si tratta di usare queste proprietà non posso semplicemente usare

myFoo.Bar.Value: = 1;

Devo usare

var 
    myBar : TNullable<Integer>;
begin
    myBar.Value := 1;
    myFoo.Bar := myBar;
end;

Che è un po 'disordinato. Suppongo che non ci possa essere nulla che io possa fare per questo.

  • Riferimenti circolari

Mi piace separare le classi in unità diverse.

vale a dire:

mantenendo l'interfaccia utente separata dalla logica di controllo e dal livello logico del modello e dei dati.

Posso avere una situazione in cui 2 classi possono fare riferimento l'una all'altra. Mentre questa è una situazione che per la maggior parte vorrei evitare, ci sono occasioni in cui è necessario.

ad esempio

unit u_A;

interface

uses
  u_B
  ;

type 
  TA = class
    public
       Foo : TB;
  end;

implementation

end;

e un'altra unità

unit u_B;

interface

uses
  u_A
  ;

type 
  TB = class
    public
       Foo : TA;
  end;

implementation

end;

Questo codice è rotto perché le due classi si includono l'una con l'altra e questo non può essere fatto in pascal. Questo non è un problema in C #. Soluzioni a cui posso pensare: 1. Includere entrambe le classi nella stessa unità, anche se questo è un problema se non penso che questo si adatti al design. 2. Crea un'altra interfaccia genitore per B ed eredita B da quella, quindi la circonda. Anche se questo è complicato per un compito così semplice.

  • Classi statiche

Non ci sono classi statiche in Delphi, queste sono utili per le classi di controllo.

  • Le migliori classi contenitore da utilizzare in Delphi

Attualmente sto usando TList e TObjectList in Generics.Collections Sono stati introdotti in Delphi XE, spero che questi siano i migliori da usare poiché delphi 7 non sembra avere buone opzioni.

Sto ancora pensando ai gestori di eventi e ad eventuali problemi che potrebbero sorgere in quel luogo. Forse ci sono altri problemi che non ho ancora pensato.

Grazie per qualsiasi consiglio.

    
posta sav 02.08.2014 - 03:47
fonte

1 risposta

8

Dovresti esaminare Spring4D dato che contiene già tipi annullabili (un'implementazione simile alla tua con un piccolo sovraccarico di operatore in più) e tipi di raccolta più potenti di quelli della RTL. Sono anche interfacciati, il che è molto utile perché non devi preoccuparti della gestione della durata, specialmente quando li passi in giro.

Per i problemi di riferimento incrociato suggerisco di codificare le interfacce e usarle come riferimento in un'altra implementazione piuttosto che 2 implementazioni che si conoscono.

Per quanto riguarda la parte MVVM, potresti guardare in DSharp che ha una prima versione di una porta Micro Caliburn per Delphi. Si tratta di uno stadio molto iniziale e difficilmente documentato, ma è possibile ottenere alcune idee su come ottenere MVVM in Delphi utilizzando la GUI ad accoppiamento libero e la logica di business connessa con i binding di dati. La rivista Blaise Pascal aveva due articoli a riguardo se sei più interessato.

P.S. Immagino tu voglia dire che stai usando XE6 in quanto è l'ultima versione.

    
risposta data 05.08.2014 - 10:38
fonte

Leggi altre domande sui tag