Lazarus

Programming => General => Topic started by: Thaddy on February 12, 2018, 10:26:38 am

Title: Defensive programming
Post by: Thaddy on February 12, 2018, 10:26:38 am
I started a wiki topic on defensive programming techniques.
The first chapter is on range errors, how to debug them and how to prevent them.
I tried to write it for both beginners and intermediate programmers.
Tell me what you think. Advice and critique is welcome.
http://wiki.freepascal.org/Defensive_programming_techniques
Title: Re: Defensive programming
Post by: minesadorada on February 12, 2018, 10:37:23 am
Looking good so far - thanks!

Some suggested additions for "defensive maintenance"
1. Initial project organisation - filenames and structures, using includes, version control models, resource planning
2. Naming schemes and commenting code for future maintenance (maybe by another programmer)
3. Pros and cons of OOP for minimising bugs
4. Using strict type checking to advantage
5. Considerations for possible future multiplatform deployment and/or multilanguage deployment
6. Recent (V1.8+) language features that enhance defensive programming (e.g. generics, UTF string issues)
7. Unit testing schemes
8. Avoiding "code creep" and bloat by defensive initial planning

You could split some topics into wiki sub-pages and/or reference existing wiki articles to prevent the main page from getting too long.
Title: Re: Defensive programming
Post by: Zoran on February 12, 2018, 10:39:50 am
I started a wiki topic on defensive programming techniques.
The first chapter is on range errors, how to debug them and how to prevent them.
I tried to write it for both beginners and intermediate programmers.
Tell me what you think. Advice and critique is welcome.
http://wiki.freepascal.org/Defensive_programming_techniques

Nice, I like it.

In "for in..." example, you wrote in comment "I is not an index", but you use it as index first. So, I would change that example:
Code: Pascal  [Select][+][-]
  1. program dtp_1d;
  2. {$mode objfpc}{$R+}
  3. var
  4.   anArray:array[0..9] of integer; // ten elements
  5.   I: Low(anArray)..High(anArray);
  6.   N: integer; // N is an integer here: it is not an index, but a value from the array
  7. begin
  8.   // data to show what for in do does
  9.   for i := Low(anArray) to High(anArray) do anArray[i] := 100+i;
  10.   for N in anArray do  // for every integer value that is contained in the array
  11.     write(N:4); // writes the value of an array cell, this is not an index.
  12. end.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 10:50:49 am
@Zoran
Fixed. Introduced j for integer value and use i as a traditional index.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 10:54:17 am
Looking good so far - thanks!
I will certainly take your tips into account. First I will write some subjects on simple proper programming like try/finally, ioresult vs exceptions, string-handling, pointer types, that kind of stuff.
After that we can expand to more advanced subjects.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 11:24:36 am
BTW added a bonus subject: use a range? You may want a set too...
Title: Re: Defensive programming
Post by: ahiggins on February 12, 2018, 02:16:15 pm
Excellent article promoting best practice. Many thanks.
Title: Re: Defensive programming
Post by: valdir.marcos on February 12, 2018, 04:23:52 pm
Excellent article. Thanks.
Title: Re: Defensive programming
Post by: Handoko on February 12, 2018, 05:10:04 pm
Great, a must-read guide for Pascal users.
Thank you.

May I suggest something?
- How to use Heaptrc to test memory leak
- Need to mention: by default all checks are disabled (IO, range, overflow, stack, etc)
- A newbie ever asked, why they are disabled by default?

Below I provide a screenshot of Lazarus default settings for debugging:
Title: Re: Defensive programming
Post by: wp on February 12, 2018, 05:17:14 pm
Nice reading!

Currently the Lazarus book is being rewritten. Why don't you contact the editor Detlef Overbeck (editor@blaisepascal.eu) and propose your text as a chapter?
Title: Re: Defensive programming
Post by: silvestre on February 12, 2018, 05:35:49 pm
Great article and very nice reading. There are many dark subjects to deal with. Memory leaks, debugger usage, etc.

I encourage the author to write more on the subject, he will have many followers... :)
Title: Re: Defensive programming
Post by: howardpc on February 12, 2018, 05:44:04 pm
Great stuff, Thaddy.
One further suggestion. In the "for in do..." example use an array of Char (or an array of some non-numeric type). This would make the difference between the array index and the array element obvious, and you would not need to say "j is not an index" etc.
It is also worth pointing out the read-only nature of the variable used in the syntax "for element-variable in anArray do", not only because the compiler cannot always detect attempts to alter element-variable's value, but also because it is an unexpected restriction.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 06:25:18 pm
Tnx so far, there is more to come. And a big thanks for formatting the hints: just what I hoped for.  Thanx Kai!!!
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 07:12:48 pm
Great stuff, Thaddy.
One further suggestion. In the "for in do..." example use an array of Char (or an array of some non-numeric type). This would make the difference between the array index and the array element obvious, and you would not need to say "j is not an index" etc.
It is also worth pointing out the read-only nature of the variable used in the syntax "for element-variable in anArray do", not only because the compiler cannot always detect attempts to alter element-variable's value, but also because it is an unexpected restriction.
Good suggestion. Feel free to correct any obvious language mistakes (?!) and discuss the above kind of valuable suggestions in this thread. I already have some rephrasing to do for tomorrow. :(
Title: Re: Defensive programming
Post by: GAN on February 12, 2018, 08:04:59 pm
I like it! I look forward to good examples of try.. Finally.

Thank you.
Title: Re: Defensive programming
Post by: eny on February 12, 2018, 08:15:43 pm
I would not waste too much real estate on erroneous code.
Show the examples how it should be done and only briefly mention the pitfalls.
Title: Re: Defensive programming
Post by: wp on February 12, 2018, 08:27:52 pm
I would not waste too much real estate on erroneous code.
Show the examples how it should be done and only briefly mention the pitfalls.
No - the tutorial is much more instructive this way, with erroneos code.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 08:59:44 pm
@eny
@wp
That's my intention because what seems obvious is not so obvious in the real world. I intentionally create "easy to spot" bugs that are often much harder to spot, but the same kind of bug.
Think 100.000 lines of code (I have done much more than that - within a team - in some jobs).
It must be manageable, repeatable and understandable.
Feel free to help me! It's a wiki! Only thing is: let me fill in the empty subjects first: I have code for that. And carefully weighted text.
Also note it is about defensive programming, not programming...(well, it is... :D :D :D )

Note it is actually very hard to create common bugs.....for educational purposes.. And that what is needed to teac defensive programming: start with the error.
And... eny... did you know that? "use ranges instead of integers for your index and think about range when writing your code! It will prevent you from introducing range errors and you will catch them at compile time."..... :P
Title: Re: Defensive programming
Post by: lainz on February 12, 2018, 09:15:44 pm
Nice article in progress.

I agree on that instead of using J for the for.. in you can change it to "item" or "element", that is common in forEach (JS) and is more descriptive.
Title: Re: Defensive programming
Post by: Thaddy on February 12, 2018, 09:19:27 pm
Point taken, lainz.
Also a good suggestion.

Question: should I split low() high() from range?
[edit] Now it reads item... tnx!! I didn't change it everywhere, though.
May solve Howardpc's issue too. will think.
Title: Re: Defensive programming
Post by: Zath on February 13, 2018, 01:11:06 am
Very nice, I hope you complete it.
I like the idea of a range and then set of range. Made sense to me first time too, not a common occurrence !
Title: Re: Defensive programming
Post by: eny on February 13, 2018, 06:33:49 pm
No - the tutorial is much more instructive this way, with erroneos code.
Of course not.
When I want to learn another language, I do not want to first see a long list of erroneous examples.
And then have to dig for the right words or phrases.
I want to see how I can properly use the language elements.
Exactly the same with this.

To make the topic useable, instruct people how to properly use the language constructs (indeed use ranges and predefined set types where applicable).
But do not let them dig through randomly chosen erroneous code fragments and at the end force them to forget all of the above, and make them remember the last bits that supposedly are correct(-ish).

Would be funny if people went to any training, school or course, and half of the time get explained how nót to do something.
Waste of time.
Title: Re: Defensive programming
Post by: del on February 13, 2018, 06:52:22 pm
I like it. After many years my brain is very "C" like but you can't play fast and loose with memory in Pascal either. This range discipline stuff is pretty slick. If there's any doubt I usually clip or modulus my indices - but that's kinda sloppy.
Title: Re: Defensive programming
Post by: wp on February 13, 2018, 07:45:26 pm
No - the tutorial is much more instructive this way, with erroneos code.
Of course not.
When I want to learn another language, I do not want to first see a long list of erroneous examples.
And then have to dig for the right words or phrases.
I want to see how I can properly use the language elements.
Exactly the same with this.

To make the topic useable, instruct people how to properly use the language constructs (indeed use ranges and predefined set types where applicable).
But do not let them dig through randomly chosen erroneous code fragments and at the end force them to forget all of the above, and make them remember the last bits that supposedly are correct(-ish).

Would be funny if people went to any training, school or course, and half of the time get explained how nót to do something.
Waste of time.

This would be correct if this wiki would address beginners. But it does not. A beginner will not understand what Thaddy is talking about. But if the reader at least has some experience Thaddy's approach is much more instructive because the reader always can compare his own coding practice with the "correct" one. He directly sees the code which he normally would type and can find what's wrong with it.
Title: Re: Defensive programming
Post by: SymbolicFrank on February 14, 2018, 07:16:15 pm
This is actually about: never declare something more than once.

Two other good ones would be: never expect your parameters to hold legal values, and don't optimize anything before it really is too slow or complex.

If you want, I'll add those and more myself.
Title: Re: Defensive programming
Post by: Mike.Cornflake on February 25, 2018, 01:29:48 am
http://wiki.freepascal.org/Defensive_programming_techniques

Awesome.  Took me far too long to get into a defensive mindset - now I push it on every beginner I find.  Having a reference document set up makes that far easier.  Many thanks, and good luck
Title: Re: Defensive programming
Post by: kupferstecher on April 11, 2018, 12:21:13 pm
How about iterations through lists? Like TList and TStrings and descendants. Is it it somehow possible to use the IN keyword there?

Code: Pascal  [Select][+][-]
  1. for ii in MyList.___ do;

Is any property/field capable of providing that information?
Currently I do it like that (which is ugly...):
Code: Pascal  [Select][+][-]
  1. for ii:= 0 to MyList.count-1 do;


@Thaddy: When do you go on with the other chapters?  :)
Title: Re: Defensive programming
Post by: RayoGlauco on April 11, 2018, 12:41:43 pm
kupferstecher, you can do like this:

Code: Pascal  [Select][+][-]
  1. var slist:tStringList; plist:tList; s:string; p:pointer;
  2. begin
  3.   ... // initialize lists
  4.   for s in slist do;
  5.   for p in plist do;
  6. end;    
Title: Re: Defensive programming
Post by: kupferstecher on April 11, 2018, 01:47:15 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;    
Title: Re: Defensive programming
Post by: Thaddy on April 11, 2018, 02:10:13 pm
I have two more chapters written and almost ready (1 short, 1 very long) but "simple" examples need extensive testing. Especially when some of them need to fail in a not very obvious way....That is harder than you might think.
Probably over the weekend.
Title: Re: Defensive programming
Post by: Thaddy 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.
Title: Re: Defensive programming
Post by: ASerge 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?
Title: Re: Defensive programming
Post by: kupferstecher 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".
Title: Re: Defensive programming
Post by: rvk 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.
Title: Re: Defensive programming
Post by: ASerge 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.
Title: Re: Defensive programming
Post by: kupferstecher 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( * );
Title: Re: Defensive programming
Post by: howardpc 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.
Title: Re: Defensive programming
Post by: kupferstecher 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). :)
Title: Re: Defensive programming
Post by: wp 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;
Title: Re: Defensive programming
Post by: lainz 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.
Title: Re: Defensive programming
Post by: taazz 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.
Title: Re: Defensive programming
Post by: lainz 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.

Title: Re: Defensive programming
Post by: taazz 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.
Title: Re: Defensive programming
Post by: lainz 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.
Title: Re: Defensive programming
Post by: lainz 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.
Title: Re: Defensive programming
Post by: taazz on April 12, 2018, 05:20:15 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?
True local variables are not initialized. but you can write statements like
Code: Pascal  [Select][+][-]
  1. procedure Test;
  2. var
  3.   MyObj :TLabel = nil;
  4.   MyText:String = '';
  5.   MyInt  :Integer = 0;
  6. begin
  7. end;
  8.  
which will add initialization code to your variables. (if you are not pulling my leg that is).
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.
yeah the initialization of the global and class fields is more of a function of the memory manager returning memory filled with zeros than a deliberate field initialization from the compiler.
Title: Re: Defensive programming
Post by: howardpc on April 12, 2018, 10:19:20 am
How about iterations through lists? Like TList and TStrings and descendants. Is it it somehow possible to use the IN keyword there?

Code: Pascal  [Select][+][-]
  1. for ii in MyList.___ do;

Provided the list has an enumerator (of type TEnumerator) you can iterate using the Object Pascal "for x in list_of_x do ..." syntax.
Most RTL container classes come with one or more enumerators already.
If there is no built-in enumerator, you can write one yourself, and FPC is sufficiently well-designed to use the enumerator you provide.
The enumeration, of course, is based on the type of the element in the container. So for TList and TFPList which which are basically arrays of pointers the enumerator assumes a pointer element, which then usually required casting. For TObjectList the enumerator is a TObject, which usually requires casting, and so on. But delphi mode is not as strict as objfpc mode, so in some cases a cast is not required.
From the point of view of defensive programming, the looser delphi mode is less type-safe, but perhaps more convenient.

A dynamic array of TLabel gives you both type-safety and built-in "for ... in ... do" syntax, and no need for any casting.
Of course it is not "generic" either, like TList, holding only TLabel references and nothing else.
Code: Pascal  [Select][+][-]
  1. type
  2.   TLabelList = array of TLabel;
  3. ...
  4. var
  5.   Llist: TLabelList;
  6.   lbl: TLabel;
  7. begin
  8.   // initialise Llist ...
  9.   for lbl in Llist do
  10.     lbl.Color := clRed;
  11.     ...
In this code the compiler will stop you using anything but a TLabel as the enumerator.
The compiler also prevents you from doing any kind of assignment to the loop variable lbl. It is read-only.
Title: Re: Defensive programming
Post by: ASerge on April 12, 2018, 05:06:00 pm
...For TObjectList the enumerator is a TObject, which usually requires casting, and so on.
Amendment. TObjectList does not override enumerator, i.e. it uses inherited from TList.
Title: Re: Defensive programming
Post by: Thaddy on April 12, 2018, 05:56:46 pm
That's true, but it works without a cast because of the result type of TObjectList. That should - but not tested - also work in ObjFpc mode not only in delphi mode.
Title: Re: Defensive programming
Post by: lainz on April 15, 2018, 10:39:24 pm
True local variables are not initialized. but you can write statements like
Code: Pascal  [Select][+][-]
  1. procedure Test;
  2. var
  3.   MyObj :TLabel = nil;
  4.   MyText:String = '';
  5.   MyInt  :Integer = 0;
  6. begin
  7. end;
  8.  
which will add initialization code to your variables. (if you are not pulling my leg that is).

Thanks, I did not use that too much.

And no, I'm beign serious, I really don't know everything about Pascal.

Maybe I've readed that some day in the manual, but with no using it directly, problems happens, and I sometimes can't figure why.
Title: Re: Defensive programming
Post by: damieiro on August 29, 2021, 07:21:58 pm
Hi thaddy!

Sorry for kicking this topic (>120 days) but i liked a lot the view of the tutorial, and even oldies can learn from it (me too :) )

Really I like it like a "good practices" in coding not only for defensive programming (and even offensive ones, i like this branch of defensive coding too)

Is this project continuated or something like good practices and book of examples (more than code snipets) i have see on wiki?

I think not knowing only what to do, but knowing why is should be do is a great engineer job. And i see this article as a little gem.
Are there more communty jobs like it? How can be started this job or continue yours? (i would like to make a "good practices wiki reviewed/written by all community).


Title: Re: Defensive programming
Post by: ArminLinder on August 30, 2021, 02:20:12 pm
Advocate this! Being somewhere in between beginner and mediocre Pascal programmer I read the wiki with interest, and looked forward for the missing parts. They'd provide more insight into why some code looks over-complicated at first, but here you get the reasons why the really experienced guys do sometimes write a couple of lines more to prevent common mistakes.

Unfortunately it was never continued.

Armin.

Btw ...
Code: Pascal  [Select][+][-]
  1. [....]
  2. var
  3.       I: Low(anArray)..High(anArray);
  4. [....]
  5. begin
  6.       for i := Low(anArray) to High(anArray) do anArray[i] := 100+i;
  7. end;
  8.  

What's the gain to subrange the loop counter (I)? Does that really make sense if it is used in a for low(...) to high(...) loop? Looks like overkill to me.

Title: Re: Defensive programming
Post by: ccrause on August 30, 2021, 02:54:51 pm
Btw ...
Code: Pascal  [Select][+][-]
  1. [....]
  2. var
  3.       I: Low(anArray)..High(anArray);
  4. [....]
  5. begin
  6.       for i := Low(anArray) to High(anArray) do anArray[i] := 100+i;
  7. end;
  8.  

What's the gain to subrange the loop counter (I)? Does that really make sense if it is used in a for low(...) to high(...) loop? Looks like overkill to me.
In this specific example it may seem like overkill since the loop range is also limited to valid values.  However it will guard against some faulty refactoring of say the for loop in future, for example substituting the low(anArray) with 0 in the for loop (because it is more "compact"):
Code: Pascal  [Select][+][-]
  1. [....]
  2. var
  3.       I: Low(anArray)..High(anArray);
  4. [....]
  5. begin
  6.       for i := 0 to High(anArray) do anArray[i] := 100+i;
  7. end;

Now if anArray is declared as follows:
Code: Pascal  [Select][+][-]
  1. var
  2.   anArray: array[1..10] of integer;
and the above modified for loop is compiled you should get a compile time error, as explained in the article.
Title: Re: Defensive programming
Post by: Zvoni on August 30, 2021, 03:09:31 pm
Addition to ccrause: Don't forget the use of Sets.
Like the article explained it's very easy that way to walk through an array just accessing the "odd" members
Title: Re: Defensive programming
Post by: damieiro on August 30, 2021, 04:52:41 pm
I love the Sets part of the article. I have misused them a lot.

For the defensive techiques are some universal ones (not only languaje driven)
A classic "defense" for indexes is like that:

Code: Pascal  [Select][+][-]
  1. program dtp_1d2;
  2. {$mode objfpc}{$R+}
  3.  
  4. const
  5.   anArrayIdxL=0;  //or other kind of naming
  6.   anArrayIdxH=9;
  7.  
  8. var
  9.   anArray:array [anArrayIdxL..anArrayIdxH] of integer;
  10.   i:shortint; // it can be as a set, like thaddy shows. i:anArrayIdxL..anArrayIdxH, but too verbose to my taste
  11.  
  12. begin
  13.   // data to show what for in do does
  14.   for i := anArrayidxL to anArrayidxH do
  15.   begin
  16.     anArray[i] := i;
  17.     write(anArray[i]:3);
  18.   end;
  19.  
  20.   readln;
  21. end.  
Title: Re: Defensive programming
Post by: Thaddy on September 27, 2021, 08:55:09 pm
Finally, from Oct 1st I have some time left to add to my article. I will keep you posted for updates.
TinyPortal © 2005-2018