Recent

Author Topic: Defensive programming  (Read 19041 times)

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Defensive programming
« Reply #30 on: April 11, 2018, 02:42:20 pm »
Thats great, thanks!
I did some trials and the following seems to work as well. I don't like the type cast, but seems not possible without it.
Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tList;
  3.   lbl:TLabel;
  4. begin
  5.   ... // initialize lists
  6.   for pointer(lbl) in LabelList do lbl.Color:= clRed;
  7. end;    

The reason is that you use the TList from classes. If you use the TList<> from FGL ot rtl-generics you don't need the pointer cast.
Alternatively, in this case you could use the TObjectList from Contnrs and the pointer can also be omitted.
Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tObjectList;
  3.   lbl:TLabel;
  4. begin
  5.   // initialize lists
  6.   for lbl in LabelList do lbl.Color:= clRed;
  7. end;

If it has to be lightweight, Tlist + pointercast is smaller...The others are safer.
« Last Edit: April 11, 2018, 02:47:31 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

ASerge

  • Hero Member
  • *****
  • Posts: 2249
Re: Defensive programming
« Reply #31 on: April 11, 2018, 06:24:07 pm »
Alternatively, in this case you could use the TObjectList from Contnrs and the pointer can also be omitted.
Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tObjectList;
  3.   lbl:TLabel;
  4. begin
  5.   // initialize lists
  6.   for lbl in LabelList do lbl.Color:= clRed;
  7. end;
Just like this? ;D And if you try to compile it?

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Defensive programming
« Reply #32 on: April 11, 2018, 07:06:55 pm »
That is harder than you might think.
I just thought you might have forgotten to go on, or other priorities.  :)


Alternatively, in this case you could use the TObjectList from Contnrs and the pointer can also be omitted.
Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tObjectList;
  3.   lbl:TLabel;
  4. begin
  5.   // initialize lists
  6.   for lbl in LabelList do lbl.Color:= clRed;
  7. end;
  8.  
I just tested, as ASerge said it doesn't compile.
Same error as for TList: Incompatible Types: Got "Pointer" expected "TLabel".

rvk

  • Hero Member
  • *****
  • Posts: 6169
Re: Defensive programming
« Reply #33 on: April 11, 2018, 09:09:29 pm »
Just like this? ;D And if you try to compile it?
Compiles fine with {$mode delphi}.
But yeah, that should have been mentioned.

ASerge

  • Hero Member
  • *****
  • Posts: 2249
Re: Defensive programming
« Reply #34 on: April 11, 2018, 10:28:44 pm »
Compiles fine with {$mode delphi}.
But yeah, that should have been mentioned.
Considering that in {$mode delphi} it works also with TList.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Defensive programming
« Reply #35 on: April 11, 2018, 11:03:03 pm »
I think that syntax
Code: Pascal  [Select][+][-]
  1. for pointer(lbl) in LabelList do;
is quite strange. Downcasts from a class (here TLabel) to pointer normally workes implicit. But the variable lbl in the loop is to get assigned. So the compiler actually reverses the downcast
Code: Pascal  [Select][+][-]
  1.  * := pointer(lbl);
to
Code: Pascal  [Select][+][-]
  1. lbl:= TLabel( * );

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Defensive programming
« Reply #36 on: April 11, 2018, 11:21:59 pm »
I think that syntax
Code: Pascal  [Select][+][-]
  1. for pointer(lbl) in LabelList do;
is quite strange. Downcasts from a class (here TLabel) to pointer normally workes implicit. But the variable lbl in the loop is to get assigned. ...

No, your code does not assign a value to lbl. The compiler would not allow this loop variable assignment in any case.
The assignment is to a TLabel property (you change the Color to clRed).
This is OK since you are not writing to lbl, but to one of its properties.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Defensive programming
« Reply #37 on: April 11, 2018, 11:55:32 pm »
Wikipedia:
"a pointer is a programming language object, whose value refers to (or "points to") another value stored elsewhere"
The value of a pointer is the address.

So I think the code DOES assign the address of each element of the LabelList one after another. And this assignment seems to need type casting (in a strange way). :)

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Defensive programming
« Reply #38 on: April 12, 2018, 12:59:24 am »
Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tObjectList;
  3.   lbl:TLabel;
  4. begin
  5.   // initialize lists
  6.   for lbl in LabelList do lbl.Color:= clRed;
  7. end;

I would not call this "defensive programming". Because LabelList is a TObjectList which can hold any TObject instances, not just TLabel's. To be on the safe side a bit more typing is required.

Code: Pascal  [Select][+][-]
  1. var
  2.   LabelList:tObjectList;
  3.   obj:TLabel;
  4. begin
  5.   // initialize lists
  6.   for obj in LabelList do if obj is TLabel then TLabel(obj).Color:= clRed;
  7. end;

lainz

  • Hero Member
  • *****
  • Posts: 4473
    • https://lainz.github.io/
Re: Defensive programming
« Reply #39 on: April 12, 2018, 02:53:11 am »
Yes, but if you don't add nothing more than TLabel there is no need to extra checking.

For example, I have lists of TJSONData, and I know that there is nothing more. Even better, if there is something more is a bug and need to be fixed.

But, if you're iterating an array of any object, yes, then it has sense.

If you need to check more, also check if objects (Labels) are assigned. That can happen, you assign something and then free it or it's freed by another part of the code. Well, that should not happen also!

But I also see the point, to catch errors or prevent them.

If you go all defensive, check if is assigned and as you say, if it's TLabel.
« Last Edit: April 12, 2018, 03:10:46 am by lainz »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Defensive programming
« Reply #40 on: April 12, 2018, 04:45:45 am »
If you go all defensive, check if is assigned and as you say, if it's TLabel.
I'm guessing some kind of trolling? If not then assign(anyobject that's not nil) will always return true and TxxxxxList will always return <> nil aka the last known correct address.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

lainz

  • Hero Member
  • *****
  • Posts: 4473
    • https://lainz.github.io/
Re: Defensive programming
« Reply #41 on: April 12, 2018, 04:52:19 am »
No. I'm not trolling.

I had that problem for real.

A list of objects linked to UI. When updating the list from internet then objects in UI (listbox) these doesn't exist anymore because was freed and replaced.

So if I understand you correctly it says that is also assigned?Well I don't exactly remember. But you're more experienced than me so I m sure you're right.


taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Defensive programming
« Reply #42 on: April 12, 2018, 04:57:15 am »
No. I'm not trolling.

I had that problem for real.

A list of objects linked to UI. When updating the list from internet then objects in UI (listbox) these doesn't exist anymore because was freed and replaced.

So if I understand you correctly it says that is also assigned?Well I don't exactly remember. But you're more experienced than me so I m sure you're right.
well yes assigned should return true unless some one has gone through the list and replaced the address with nil, in which case if xxxx is Tlabel should return false making the assigned check superfluous.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

lainz

  • Hero Member
  • *****
  • Posts: 4473
    • https://lainz.github.io/
Re: Defensive programming
« Reply #43 on: April 12, 2018, 05:02:21 am »
I see. Thanks!

Now I'm understanding a bit more. Another question: objects in local variables inside a function are not initialized with nil?

Because I had that problems today. Checking for nil to an uninstantiated object something like

If assigned (obj1) then obj1.free;

And I get exceptions.

Sorry I'm more used to JS that starts with undefined or null.

lainz

  • Hero Member
  • *****
  • Posts: 4473
    • https://lainz.github.io/
Re: Defensive programming
« Reply #44 on: April 12, 2018, 05:15:07 am »
That  will be good to add to the guide.

I feed you Thaddy with a lot of common mistakes :-)

These are easy to find for me.

 

TinyPortal © 2005-2018