Thursday, June 09, 2005

The problem with "with"

Something that I strongly discourage Delphi developers from using is the with statement. I never used to dislike the with statement until I got burned pretty badly by a bug caused by the use of one.

You can't debug the with statement.
You can't watch a property if it's in a with block (check out my example), there is no tool tip evaluation for these properties either.

Small example showing the hazards of debugging a with statement.

1. Create a new win32 application (steps for D2005 - should be the same for all Delphi versions)
2. Add a button to the form
3. Create an OnCreate event
4. Add the following code:
   procedure TForm1.FormCreate(Sender: TObject);
   begin
       with Button1 do
          Caption := 'Hello';
   end;
5. Put a breakpoint on the with line and add Caption to the watch list.
6. Run the application and press the button.

Although it's probably better that the debugger doesn't cope with this as it might encourage more widespread use of with.

Perhaps the compiler should be enhanced to fulfil the request of this report in QualityCentral?

Defect No: 2667 Status: ReportedAdd ambiguous warnings to WITH statements
http://qc.borland.com/wc/wc.exe/details?ReportID=2667

One final thing before I end this post. The VCL is starting to get a large number of with statements added to it and it needs to stop. Especially in message handlers where you often see the following:

   with Message do
   begin
      // 30 lines of code here
   end;

The string "with Message do" was found 101 times in my D2005 VCL source. Think the 30 lines is an overstatement? Open up Forms.pas and check out the TCustomForm.WndProc method (it's over 100 lines).

This makes debugging a nightmare. If you debug the VCL often (as I do) and find this annoying, you may want to vote for the following QualityCentral report:
Defect No: 13515 Status: Reported
Remove all occurrences of the with statement from the VCL
http://qc.borland.com/wc/wc.exe/details?ReportID=13515

Looking for a QualityCentral win32 client?
Check out my QC Client - tentatively called JED, QC from http://www.jed-software.com/.
Want to beta test the soon to be released Version 1 (mega changes from the website version)? Send me an email requesting the download information (email on website).

3 Comments:

Blogger Albert Research said...

Well.. I understand your point of view... but if you use correctly the with statement... it cleans up a lot of your code... for me ich much clearer following code


with V_Test do
begin
tst_Code := 0;
tst_Name := 'AA';
... (10 fiels more)
end;

as
V_Test.tst_Code := 0;
V_Test.tst_Name := 'AA';
... (10 field more)..

6:08 PM  
Anonymous Anonymous said...

Our firm decided to remove all "with" from our code after some occurencies of such bug:

procedure T2.P2;
...
with I1 do
begin
..
P1;
..
end;
...

where I1 is some interface, but there is no procedure P1 in it. After adding P1 to I1 (seems to be completely safe operation :-) above code become wrong, it calls I1.P1 instead of Self.P1. The worst thing is that programmer who added P1 to interface I1 haven't any chance to know about bug, it can be catched only by tests...

10:54 PM  
Anonymous Anonymous said...

I agree and disagree, ie. I agree with Jed and disagree with Albert Research. I actually find the second bit of code in Albert's example clearer and easier to understand.

"With" statements become a real nightmare when they are nested as it becomes very difficult to determine what properties belong to what.

Steve

11:13 AM  

Post a Comment

<< Home