Jump to content
Mike Torrettinni

Disadvantage of using defined type of TArray?

Recommended Posts

20 minutes ago, Vandrovnik said:

In 10.3.3, it is better, usually rename finds all places, but sometimes it does not and finds for example just 10 of 30.

Skipping 10.3.x altogether. Will see how 10.4 updates will be successful.

Share this post


Link to post
Posted (edited)
7 hours ago, Vandrovnik said:

In 10.3.3, it is better, usually rename finds all places, but sometimes it does not and finds for example just 10 of 30.

Exactly, to find something is not very reliable or convenient, with Rx10.4 LSP this is getting somewhat better in the right direction, but not perfect.
Maybe Uwes MMX-Tool fills that gap, but I'm still learning howto use it at best.

Still I'll do a lot of intensive "search and replace" with external tools, which gave me much better feeling of reliability.

Edited by Rollo62

Share this post


Link to post

While refactoring is still not perfect and does not work every time, I could improve it with turning off "View references before refactoring".

 

  • Like 1

Share this post


Link to post
4 hours ago, Rollo62 said:

Maybe Uwes MMX-Tool fills that gap,

Not really. Besides only working inside the current unit, ist is merely a find and replace respecting some scope.

  • Like 1

Share this post


Link to post

Strong typing may be a good idea in some context.

 

For instance, in DDD (Domain Driven Design) you should better define your genuine types.

Instead of writing:

type
  TUser = record
    Name: string;
    FirstName: string;
  end;

You should rather define:

type
  TUserName = type string;

  TUserFirstName = type string;

  TUser = record
    Name: TUserName;
    FirstName: TUserFirstName;
  end;

  TUsers = type TArray<TUser>;

and so on for any service methods.

 

Such strong typing (T* = type ### defines its own strong type) helps maintaining complex code.

 

I always let people remember the https://en.wikipedia.org/wiki/Mars_Climate_Orbiter disaster.
A strong type (as it should have been if ADA would still have been used for the software) would have ensured that the force would use the same unit in the inter-module computation (english vs metric systems).

Specific types may help e.g. for "Design by contract".

 

Of course, for a DTO you may just use plain string/TArray<string>.

But if you want to have some maintainable long-term code, consider define your own types.

See e.g. http://blog.synopse.info/post/2019/09/18/Introducing-Kingdom-Driven-Design-at-EKON-23

 

 

  • Like 2

Share this post


Link to post
6 hours ago, Arnaud Bouchez said:

TUserName = type string;

OK, I've never seen this, and the more I read about it, the more confused I am what it is used for. I understand it becomes new string type, compatible with just string. But I don't see how it's useful.

Share this post


Link to post
2 hours ago, Mike Torrettinni said:

OK, I've never seen this, and the more I read about it, the more confused I am what it is used for. I understand it becomes new string type, compatible with just string. But I don't see how it's useful.

It is useful and will save you time in long run and will avoid bunch of problem down the road, i use sometimes to replace even simpler types like Integer, for me changing an existing code is time consuming and tend to be error prone more than writing new one,

here an example on how this save time 

TSessionID been used to replace Integer, forcing myself to use helper with it, that server was and still using it for identifying the connection sessions per run and it was initialized to 0 per restart, years later the server become 64bit and i didn't touch anything except the session type in the code making it Int64, was good for a year or two then the need for longer and unique Session to be permanent over time, Int64 will not do it, server now is using cloud storage and it is more than one EXE running on different machines and in need to coordinate with some data bank, so simple and short types are out of the question, now guess how much time it took me converting TSessionID into TGUID that also have the creation time, it was less than 3 minutes to make sure the helper is comparing and returning right sort of readable string format and vice versa.

In fact i was using TSessionID for TCP connections and TUserID for users per authorization, both were Integer in the past and both are are TGUID now, think about that, i even can't mix between them, leave them TGUID and imagine one fogy brain morning what damage you can cause, TSessionID is created per TCP session while TUserID are grabbed from DB.

On other hand i didn't do that in the past for the user name and was using short strings to be fixed maximum size and fit in record nicely, because the DB user table was cached in the memory in full, it was time consuming changing anything about it, caused many bugs over time, i forced later to use strong type for it and forgot that problem, till this day every time i come across code that handle the user name i double check it in fear it still buggy, while i don't even think about session id or user id, because they were there from beginning.

Share this post


Link to post

Distinct types don't give you type safety when used with integers and strings. These distinct types are still assignment compatible. There is a use in type identity for design time  property editors. 

 

If you want type safety for assignment you'd need to wrap in a record. 

  • Like 3

Share this post


Link to post
Posted (edited)
13 hours ago, Arnaud Bouchez said:

TUsers = type TArray<TUser>;

 

Sorry to disappoint you but that does not compile but raises [dcc32 Error] E2574 Instantiated type can not be used for TYPE'd type declaration

 

13 hours ago, Arnaud Bouchez said:

A strong type (as it should have been if ADA would still have been used for the software) would have ensured that the force would use the same unit in the inter-module computation (english vs metric systems).

Specific types may help e.g. for "Design by contract".

Too bad we are working with Delphi where it does not matter because I can still assign a TUserName to TUserFirstName

Edited by Stefan Glienke
  • Like 2

Share this post


Link to post
5 hours ago, Kas Ob. said:

TSessionID been used to replace Integer

You are talking about TSessionID = integer; or TSessionID = type integer; ?

I understand the use of first one, but not the second one.

Share this post


Link to post
Posted (edited)
14 minutes ago, Mike Torrettinni said:

You are talking about TSessionID = integer; or TSessionID = type integer; ?

First one.

 

Edit

This will not prevent assignment, but will at least make you wonder in case you forgot or this is not your code, what on earth is TSessionID, so clicking find declaration you will it is simple integer but with note/comment like Use it with this helper or with that class, or don't touch its value, use functions YYY1,YYY2 in unitX to create, assign or compare

Edited by Kas Ob.

Share this post


Link to post
11 minutes ago, Kas Ob. said:

First one.

 

Edit

This will not prevent assignment, but will at least make you wonder in case you forgot or this is not your code, what on earth is TSessionID, so clicking find declaration you will it is simple integer but with note/comment like Use it with this helper or with that class, or don't touch its value, use functions YYY1,YYY2 in unitX to create, assign or compare

Great, thank you!

Do you have a real case scenario for using the second option, TSessionID = type integer; ?

Share this post


Link to post
Just now, Mike Torrettinni said:

Do you have a real case scenario for using the second option, TSessionID = type integer; ?

Nope, i like to keep things simple, used few times in the past and regret it later.

Share this post


Link to post
16 minutes ago, Mike Torrettinni said:

Do you have a real case scenario for using the second option, TSessionID = type integer; ?

For integer, due to assignment compatibility rules of the language, the only use is to provide a distinct type identity to be used in RTTI settings. For instance if you wanted to have a separate design time property editor for this type.

Share this post


Link to post
12 minutes ago, David Heffernan said:

to be used in RTTI settings

Thanks!

Sometimes such clear wording makes all the difference. Yesterday reading in official help and SO answers, I just didn't get it. Now, re-reading the same again, it makes sense.

Share this post


Link to post
Posted (edited)
22 hours ago, Stefan Glienke said:

Sorry to disappoint you but that does not compile but raises [dcc32 Error] E2574 Instantiated type can not be used for TYPE'd type declaration

The new features of this compiler are just untested/unfinished...
Even the type helpers are broken with sub-types: if you define TMyInteger = type integer then you can't use myinteger.ToString... Non-inheritance is a "feature" which IMHO is wrong.

 

What always work, and is the very same, is to write:

 

TUsers = array of TUser;

 

> Too bad we are working with Delphi where it does not matter because I can still assign a TUserName to TUserFirstName

 

Yes, only var/out variables have compile-time strong checking...
But at least you can read the code and verify the consistency either since the type (and RTTI) are explicit.
And refer to the type definition comment as documentation.

 

And it also helps writing more natural code, by having the type defined in the time, not in the parameter

 

I prefer:

 

function CopySession(source, dest: TSessionID): boolean;

....
property session: TSessionID;

 

instead of

 

function CopySession(sourceSessionID, destSessionID: integer): boolean

...

property sessionID: integer;

Edited by Arnaud Bouchez
  • Like 3

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×