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