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.
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.
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.