Where do you place your unit uses?

Where do you place your unit uses?

Over the years, I’ve come to preferring to place my uses in the Interface section only, even if its types, constants or methods only are used in the implementation section.

What is your practice, and why do you prefer one pattern over the others – or why would you recommend against one of these patterns?

unit Test;

interface

uses

ThisUnit, ThatUnit;

implementation

end.

vs

unit Test;

interface

uses

ThisUnit;

implementation

uses

ThatUnit;

end.

Scopes and names can really be deceiving.

Scopes and names can really be deceiving. A root class and a descendant class can both have public fields, properties and methods with the same name.

I really wonder why this doesn’t raise a warning or a even a hint?

(Berlin 10.1.x / Tokyo 10.2.x)

Output:

c: 1

TClass1:1

TClass1.PropTest:1

TClass2.Test:2

TClass2.PropTest:2

TClass1.Oops

Press any key:

Code:

program PublicScope;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils;

type

TClass1 = class

public

Test: Integer;

constructor Create; virtual;

procedure Dump; virtual;

procedure Oops;

property PropTest:Integer read Test;

end;

TClass2 = class(TClass1)

public

Test:Integer;

constructor Create; override;

procedure Dump; override;

procedure Oops;

property PropTest:Integer read Test;

end;

{ TClass1 }

constructor TClass1.Create;

begin

Test := 1;

end;

procedure TClass1.Dump;

begin

Writeln(‘TClass1:’, Test);

Writeln(‘TClass1.PropTest:’, Test);

end;

procedure TClass1.Oops;

begin

Writeln(‘TClass1.Oops’);

end;

{ TClass2 }

constructor TClass2.Create;

begin

Inherited;

Test := 2;

end;

procedure TClass2.Dump;

begin

Inherited;

Writeln(‘TClass2.Test:’, Test);

Writeln(‘TClass2.PropTest:’, Test);

end;

procedure TClass2.Oops;

begin

Writeln(‘TClass2.Oops’);

end;

procedure Test;

var

c: TClass1;

begin

c := TClass2.Create;

try

Writeln(‘c: ‘, c.Test);

c.Dump;

c.Oops;

finally

c.Free;

end;

end;

begin

try

try

Test;

except

on E: Exception do

Writeln(E.ClassName, ‘: ‘, E.Message);

end;

finally

Write(‘Press any key: ‘);

Readln;

end;

end.

The ARC vs non-ARC situation adds yet another layer of complexity to creating cross platform code.

The ARC vs non-ARC situation adds yet another layer of complexity to creating cross platform code. The Linux compiler uses ARC – while Windows and OSX do not.

Guess what that does to the Linux support: It falls way down on the viability list for cross platform code for servers and services. Note that I don’t mind ARC – I just don’t get why they did not move to ARC for all platforms.

They could duplicate the libs, put the old ones into care & maintenance, and introduce

arc.system. *

arc.vcl. *

arc.data. *

and so forth…

The current situation is pretty much ridiculous.

/rant

Edit: Added what I wrote in the EMBT forums.

I do not expect my non-ARC code to behave on ARC. It is after all a very different life cycle management model.

If you expect to be able to take your non-ARC code and move to Linux without changes – you are delusional.

My gripe is that I can’t really go cross platform now with the non-ARC Win32/Win64/OSX compilers. There is no way I want to maintain code that have to deal with both ARC and non-ARC life cycle management. I want to be able to have cross platform code – across ALL platfoms – without having to think ARC/Non-ARC.

I believe an ARC compliant FMX/VCL/RTL and ARC compiler on Windows and OSX (in addition to the current non-ARC) would offer the most sensible migration path for those that want cross platform, since there is no chance that the iOS and Android compilers will go non-ARC.

For those that don’t want ARC, they have to sacrifice cross platform compatibility, and probably risk a deprecated platform in a few years.

For those that want cross platform compatibility, they may have to sacrifice a bit of performance with the added complexity of ARC.

Note that the current performance problem on Android looks a completely different issue – i.e. not ARC related, since the previous versions also used ARC on that platform.

Generics, records and typecasts = F2084 Internal Error: AV0DBFFBE9-R0000000C-0

Generics, records and typecasts = F2084 Internal Error: AV0DBFFBE9-R0000000C-0

// redux – not actual code

type

TKey = record

Index: Integer;

end;

TSomeClass = class abstract

procedure CopyTo(var Key: TKey); virtual; abstract;

procedure CopyFrom(var Key: TKey); virtual; abstract;

end;

TKeyValue = record

Key: TKey;

Value: T;

end;

TIndexList = TArray;

TKeyValueList = TArray<TKeyValue>;

TSomeClass = class(TSomeClass)

public type

TValueList = TArray;

private var

ValueList: TValueList;

procedure CopyTo(var Key: TKey); override;

procedure CopyFrom(var Key: TKey); override;

end;

procedure TSomeClass .CopyTo(var Key: TKey);

begin

TKeyValue(Key).Value := ValueList[Key.Index]; // OK

end;

procedure TSomeClass .CopyFrom(var Key: TKey);

begin

ValueList[Key.Index] := TKeyValue(Key).Value; // F2084 Internal Error: AV0DBFFBE9-R0000000C-0

end;

CopyTo/From called with a list of TKeyValue params.

I guess I was asking for it. Rewrote to use regular class objects.