web-dev-qa-db-fra.com

Meilleures pratiques pour la mise en œuvre de MVVM et MVC à Delphes Pascal

Je suis un programmeur Delphi Pascal, j'utilise le dernier Embarcadero Delphi Xe et j'aimerais profiter des modèles de conception tels que le contrôleur d'affichage du modèle et le modèle de vue de mode.

Cependant, il ne semble pas y avoir beaucoup sur le Web sur les meilleures pratiques de faire cela à Pascal. La plupart des exemples que je peux trouver sont en C # et certaines des caractéristiques linguistiques ne sont pas présentes à Pascal, ce qui signifie que je devrais peut-être trouver des moyens de mettre en œuvre ces fonctionnalités.

J'essaie d'adapter le code de cet article ici

Je vais énumérer les problèmes que je suis confronté

  • types nullables

Pascal n'a pas de types nullables tels que c # le fait pour avoir créé le mien.

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;

dans la section de mise en œuvre

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;
  • Obtenir/définir des propriétés

Maintenant que j'ai un type nullable, je peux créer des propriétés nullables mais il vient avec des odeurs de code

par exemple si je crée

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

dans la section de mise en œuvre

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;

C'est bien mais quand il s'agit d'utiliser ces propriétés, je ne peux pas utiliser

myfoo.bar.value: = 1;

Je dois utiliser

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

Qui est un peu messier. Je suppose qu'il n'y a peut-être rien que je puisse faire à ce sujet.

  • Références circulaires

J'aime séparer les cours en différentes unités.

c'est à dire: structure

garder l'interface utilisateur séparément de la logique de contrôle et la couche logique du modèle et des données.

Je peux avoir une situation où 2 classes peuvent se référer mutuellement. Bien que ce soit une situation qui, pour la plupart, je voudrais éviter, il y a des occasions où cela est nécessaire.

par exemple

unit u_A;

interface

uses
  u_B
  ;

type 
  TA = class
    public
       Foo : TB;
  end;

implementation

end;

et une autre unité

unit u_B;

interface

uses
  u_A
  ;

type 
  TB = class
    public
       Foo : TA;
  end;

implementation

end;

Ce code est cassé car les deux classes sont les unes des autres et cela ne peut pas être fait à Pascal. Ce n'est pas un tel problème dans C #. Solutions que je peux penser: 1. Incluez les deux classes dans la même unité, bien que cela pose problème si je ne pense pas que cela convient à la conception. 2. Créez une autre interface parent pour B et hériter B à partir de cela, alors cela se déplace. Bien que cela soit en désordre pour une tâche aussi simple.

  • classes statiques

Il n'y a pas de classes statiques à Delphes, elles sont utiles pour les classes de contrôle.

  • Meilleures classes de conteneurs à utiliser dans Delphi

Je suis actuellement en train d'utiliser TLIST et TOBEJECTLIST en génériques.Collections qu'ils ont été introduits à Delphi Xe, j'espère que ce sont les meilleurs à utiliser depuis que Delphi 7 ne semblait avoir de bonnes options.

Je pense toujours aux gestionnaires d'événements et aux problèmes qui peuvent survenir là-bas. Peut-être y a-t-il encore d'autres problèmes que je n'ai pas encore pensé.

Merci pour tout conseil.

10
sav

Vous devriez regarder dans Spring4D car il contient déjà des types nullables (implémentation similaire que la vôtre avec un peu de surcharge de l'opérateur supplémentaire) et des types de collecte plus puissants que ceux de la RTL. Ils sont également interfacés basés sur une manière très pratique car vous n'avez pas à vous soucier de la gestion de la vie, en particulier lorsque vous les transmettez.

Pour les problèmes de référencement croisé, je suggère de coder contre les interfaces et utilisez-les comme référence dans une autre mise en œuvre plutôt que 2 implémentations en se connaissant.

Quant à la partie MVVM, vous pourriez consulter DSHARP, qui a une première version d'un Port Micro Caliburn pour Delphi. Il est très précoce et à peine documenté, mais vous pouvez obtenir des idées sur la manière de réaliser MVVM à Delphi en utilisant une interface graphique et une logique commerciale à couplage lâche connectée aux liaisons de données. Le magazine Blaise Pascal avait deux articles à ce sujet si vous êtes plus intéressé.

P.s. Je suppose que vous voulez dire que vous utilisez XE6 comme c'est la dernière version.

9
Stefan Glienke