9

I'm a Delphi pascal programmer, I use the latest Embarcadero delphi XE, and I would like to take advantage of design patterns such as Model view controller and model view view-model.

However, there doesn't seem to be much on the web about the best practices for doing this in pascal. Most of the examples that I can find are in C# and some of the language features are not present in pascal, which means I may have to find ways to implement those features.

I'm trying to adapt code from this article here

I'll list the issues that I'm facing

  • Nullable types

Pascal does not have nullable types as C# does so I have created my own.

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;

in the implementation section

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;
  • Get/Set for properties

Now that I have a nullable type I can create nullable properties However it comes with some code smells

for example if i create

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

in the implementation section

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;

This is fine but when it comes to use these properties I can't just use

myFoo.Bar.Value := 1;

I have to use

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

Which is a bit messier. I suppose there may be nothing I can do about this.

  • Circular References

I like to separate classes into different units.

ie: structure

keeping the user interface separate from the control logic and the model and data logic layer.

I can have a situation where 2 classes can reference each other. While this is a situation that for the most part I would like to avoid, there are occasions where this is needed.

for example

unit u_A;

interface

uses
  u_B
  ;

type 
  TA = class
    public
       Foo : TB;
  end;

implementation

end;

and another unit

unit u_B;

interface

uses
  u_A
  ;

type 
  TB = class
    public
       Foo : TA;
  end;

implementation

end;

This code is broken because the two classes include each other and this can not be done in pascal. This is not such a problem in C#. Solutions that I can think of: 1. include both classes in the same unit, although this is a problem if I do not think this suits the design. 2. Create another parent interface for B and inherit B from that, then this gets around it. Although this is messy for such a simple task.

  • Static classes

There aren't any static classes in Delphi, these are useful for control classes.

  • Best Container classes to use in Delphi

I'm currently using TList and TObjectList in Generics.Collections They were introduced in Delphi XE I hope these are the best to use since delphi 7 didn't seem to have any good options.

I'm still thinking about event handlers and any issues that may arise there. Perhaps there are some other issues that I have not thought of yet.

Thanks for any advice.

  • I originally asked this question on code review but it was suggested that I post here. – sav Aug 2 '14 at 1:47
8

You should look into Spring4D as it already contains nullable types (similar implementation as yours with a little extra operator overloading) and way more powerful collection types than those in the RTL. They are also interfaced based which is very handy because you don't have to worry about lifetime management especially when passing them around.

For cross referencing problems I am suggesting coding against interfaces and use these as reference in another implementation rather than 2 implementations knowing each other.

As for the MVVM part you might look into DSharp which has a first version of a Caliburn Micro port for Delphi. It is very early stage and hardly documented but you might get some ideas how to achieve MVVM in Delphi using loosely coupled GUI and business logic connected with data bindings. The Blaise Pascal magazine had two articles about it if you are more interested.

P.S. I guess you mean you are using XE6 as that is the latest version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.