Does "Long running method is done" have a design pattern? - delphi

I have got a method that takes a long time to complete and want to check regularly whether it is done. This is what I have come up with (simplified code, Delphi 2007):
type
IWaitForDone = interface
function IsDone: boolean;
end;
function TSomeClass.doSomethingThatTakesLong: IWaitForDone;
begin
Result := TClassThatDoesIt.Create;
end;
var
Waiter: IWaitForDone;
begin
Waiter := SomeClass.doSomethingThatTakesLong;
while not Waiter.isDone do
doSomethingElse;
Waiter := nil;
end;
In the context it is possible that calling isDone actually does a part of what is to be done and returns true, when finished and false while there are still parts to be done. Alternatively it could just check whether another thread is done with its work. I don't want this to be visible to the caller.
I guess that I am not the first one to come across this type of problem and this solution probably already has got a name (a design pattern?), but I could not find it.
So what is it called?

Microsoft suggests two patterns for long running methods (invoke asynchronously and rendezvous according to pattern)
Event-based Asynchronous Pattern Overview
Calling Asynchronous Methods Using IAsyncResult

Not sure if that helps/suits you, but take a look at AsyncCalls unit.

I've seen this referred to as a 'Future' before.
Here are a couple of links:
This one is by Oren Eini who is a prolific .Net developer. As an aside - it is well worth reading his blog (where this link is from) if you are interested in coding pattterns, best practices etc...
Futures post from Oren Eini (Ayende#Rahien)
And this link is yours but I thought I'd just update the answer with it to be complete.
Futures link from uni-sb.de

I'm not sure if I understand your problem correctly, but I don't like the idea that part of the actual work is done in the IsDone function (funny sentence). I would expect a method like that to just check some flag and return quickly. What if I decide not to continously call IsDone but to perform some other work and check IsDone after that? Then, no work has been done until the first call - not really what I would expect from an asynchronous call...
I didn't really answer your question, but I doubt that this is a widely used design pattern.

Related

Empty Functions - Placeholder?

so I was just looking through the Code of our inventory management system
and I saw some Snippet's of one of my Coworkers, all he does in some Functions is
simply open them and insert a command in there for example
procedure TWerkStF.TBBtnStatiClick(Sender: TObject);
begin
inherited;
//
end;
so i am wondering when you should do something like that and when is it usefull, are there some benefits?
This is not useful, and has no benefits. Such a function can, and should, be removed.
The function in the question, by using inherited, simply searches in the super classes for a function of the same name, and if one is found calls it. If one is not found then no action is performed. As a rule, such a function, one that only calls inherited, does not modify the behaviour of the program. You can remove it without changing behaviour.
We use such functions/procedures most times to tell other Co-Workers where they should not change anything, the reason for that is because some events are just not fitting the needs of some Modules, therefore we "warn" each other with empty Functions.
Sounds wiered, i know.

Wrapper class for thread-safe objects

I have recently played around with one demo opensource project for the basic functionality of the INDY10 TCP/IP server and stumbled upon the problem of internal multitasking implementation of INDY and its interaction with VCL components. Since there are many different topics in SO on the subject, I decided to make a simple client-server application and test some of the solutions and approaches suggested, at least the ones that I understood correctly. Below I would like to summarize and review an approach that was previously suggested on SO, and if possible listen to your expert opinion on the subject.
Problem: Encapsulation the VCL for thread-safe usage inside an indy10-based client/server application.
Description of the Development Env.:
Delphi Version: Delphi® XE2 Version 16.0
INDY Version 10.5.8.0
O.S. Windows 7 (32Bit)
As mentioned in the article ([ Is the VCL Thread-safe?]) (sorry I do not have enough reputation to post the link) special care should be taken when one wishes to use any kind of VCL components inside a multithreaded (multitasking) application. VCL is not thread safe, but can be used in a thread safe way!
The how and the why usually depend on the application at hand but one can attempt to generalize a bit and suggest some kind of general approach to this problem. First of all, as in the case of INDY10, one does not need to be explicitly parallelizing his code, i.e. create and execute multiple threads, in order to expose VCL to deadlocks and data inter dependencies.
In every sclient-server application, the server has to be able to handle multiple requests simultaneously, so naturally, INDY10 internally implements this functionality. This would mean that the INDY10 set of classes are responsible to manage the program's thread creation, execution and destruction procedures internally.
The most obvious place where our code is exposed to the inner workings of INDY10 and hence possible thread conflicts, is the IdTCPServerExecute (TIdTCPServer onExecute event) method.
Naturally, INDY10 provides classes (wrappers) that ensure thread-safe program flow, but since I did not manage to get enough explanation on their application and usage, I prefer a custom made approach.
Below I summarize a method ( the suggested technique is based on a previous comment I found in SO How to use TIdThreadSafe class from Indy10 ) that attempts (and presumably succeeds) in dealing with this problem:
The question I tackle below is: How to make a specific class "MyClass" ThreadSafe?
The main idea is to create kind of a wrapper class that encapsulates "MyClass" and queues the threads that try to access it in First-In-First-Out principle. The underlying objects that are used for synchronization are [Windows's Critical Section Objects.].
In the context of a client-server application, "MyClass" will contain all thread unsafe functionality of our server, so we will try to ensure that those procedures and functions are not executed by more than one working thread simultaneously. This naturally means loss of parallelism of our code, but since the approach is simple and seems to be , in some cases this maybe a useful approach.
Wrapper class Implementation:
constructor TThreadSafeObject<T>.Create(originalObject: T);
begin
tsObject := originalObject; // pass it already instantiated instance of MyClass
tsCriticalSection:= TCriticalSection.Create; // Critical section Object
end;
destructor TThreadSafeObject<T>.Destroy();
begin
FreeAndNil(tsObject);
FreeAndNil(tsCriticalSection);
inherited Destroy;
end;
function TThreadSafeObject<T>.Lock(): T;
begin
tsCriticalSection.Enter;
result:=tsObject;
end;
procedure TThreadSafeObject<T>.Unlock();
begin
tsCriticalSection.Leave;
end;
procedure TThreadSafeObject<T>.FreeOwnership();
begin
FreeAndNil(tsObject);
FreeAndNil(tsCriticalSection);
end;
MyClass Definition:
MyClass = class
public
procedure drawRandomBitmap(abitmap: TBitmap); //Draw Random Lines on TCanvas
function decToBin(i: LongInt): String; //convert decimal number to Bin.
procedure addLineToMemo(aLine: String; MemoFld: TMemo); // output message to TMemo
function randomColor(): TColor;
end;
Usage:
Since threads execute in order and wait for the thread which has the current ownership of the critical section to finish (tsCriticalSection.Enter; and tsCriticalSection.Leave;) it is logical that if you want to manage that ownership relay, you need one unique instance TThreadSafeObject (you can consider using the singleton pattern). so include:
tsMyclass:= TThreadSafeObject<MyClass>.Create(MyClass.Create);
in Form.Create and
tsMyclass.Destroy;
in Form.Close; Here tsMyclass is a global variable of type MyClass.
Usage:
Regarding the usage of MyClass try the following:
with tsMyclass.Lock do
try
addLineToMemo('MemoLine1', Memo1);
addLineToMemo('MemoLine2', Memo1);
addLineToMemo('MemoLine3', Memo1);
finally
// release ownership
tsMyclass.unlock;
end;
, where Memo1 is an instance of a TMemo component on the form.
With this, we are supposed to ensure that anything that happens when tsMyClass is locked
will be executed by only one thread at a time. An obvious drawback of this approach, however, is that since I have only one instance of tsMyclass, even if one thread is trying to draw for e.g. on the Canvas, while another is writing on the Memo, the first thread will have to wait for the second to finish and only then it will be able to carry out its job.
My questions here are:
Is the above suggested method correct? Am I still free of race
conditions or do I have some "loopholes" in the code, from where
data conflicts could occur?
How can one, in general, test for thread
unsafety of his/her applicaiton?
I would like to stress that the above approach is in no way my own doing. It is basically a summary of the solution found in 2. Nevertheless, I have decided to post again in an attempt to get some kind of closure on the topic or a kind of proof of validity for the suggested solution. Besides, repetition is mother of all knowledge, as they say.
With this, we are supposed to ensure that anything that happens when
tsMyClass is locked will be executed by only one thread at a time. An
obvious drawback of this approach, however, is that since I have only
one instance of tsMyclass, even if one thread is trying to draw for
e.g. on the Canvas, while another is writing on the Memo, the first
thread will have to wait for the second to finish and only then it
will be able to carry out its job.
I see one big problem here: the VCL (forms, drawing, etc...) lives on the main thread. Even if you block concurrent thread access, the updates need to be done in the context of the main thread. This is the part where you need to use Synhronize(), the big difference with a lock (Criticalsection) is that synchronized code is ran in the context of the main thread. The end result is basically the same, your threaded code is serialized and you lose the advantage of using threads in the first place.
Locking on the whole object can be much too coarse.
Imagine cases where some properties or methods are independent of others. If the lock works on a "global" level, many operations will be blocked needlessly.
From Reduce lock granularity – Concurrency optimization
So, how can we reduce lock granularity? With a short answer, by asking
for locks as less as possible. The basic idea is to use separate locks
to guard multiple independent state variables of a class, instead of
having only one lock in class scope.
First things first: You don't need to implement a LOCK for each of your objects, Delphi's done that for you with the TMonitor class:
TMonitor.Enter(WhateverObject);
try
// Your code goes here.
finally TMonitor.Leave(WhateverObject);
end;
just make sure you free the WhateverObject when your application shuts down, or else you'll run into a bug that I've opened on QC: http://qc.embarcadero.com/wc/qcmain.aspx?d=111795
Secondly, making an application multi-threading is a bit more involved. You can't just wrapp each call between Enter/Leave calls: your "locking" needs to take into account what the object does and what the access pattern is. Wrapping calls within Enter/Leave simply make sure that only one thread runs that method at any time, but race conditions are much more complex, and might arise from successive calls to your locked methods. Even those each method is locked, and only one thread ever called those methods at any given time, the state of the locked object might change between as a consequence of other thread's activity.
This kind of code would be just fine in a single-threaded application, but locking at method level is not enough when switching to multi-threaded:
if List.IndexOf(Something) = -1 then
List.Add(Something);

Fluent interface in Delphi

What are the pros and cons in using fluent interfaces in Delphi?
Fluent interfaces are supposed to increase the readability, but I'm a bit skeptical to have one long LOC that contains a lot of chained methods.
Are there any compiler issues?
Are there any debugging issues?
Are there any runtime/error handling issues?
Fluent interfaces are used in e.g. TStringBuilder, THTMLWriter and TGpFluentXMLBuilder.
Updated:
David Heffernan asked which issues I was concerned about. I've been given this some thought, and the overall issue is the difference between "explicitly specifying how it's done" versus "letting the compiler decide how it's done".
AFAICS, there is no documentation on how chained methods actually is handled by the compiler, nor any specification on how the compiler should treat chained methods.
In this article we can read about how the compiler adds two additional var-parameters to methods declared as functions, and that the standard calling convention puts three params in the register and the next ones on the stack. A "fluent function method" with 2 params will therefor use the stack, whereas an "ordinary procedure method" with 2 params only uses the register.
We also know that the compiler does some magic to optimize the binary (e.g. string as function result, evaluation order, ref to local proc), but sometimes with surprising side effects for the programmer.
So the fact that the memory/stack/register-management is more complex and the fact that compiler could do some magic with unintentional side effects, is pretty smelly to me. Hence the question.
After I've read the answers (very good ones), my concern is strongly reduced but my preference is still the same :)
Everybody is just writing about negative issues so let's stress some positive issues. Errr, the only positive issue - less (in some cases much less) typing.
I wrote GpFluentXMLBuilder just because I hate typing tons of code while creating XML documents. Nothing more and nothing less.
The good point with fluent interfaces is that you don't have to use them in the fluent manner if you hate the idiom. They are completely usable in a traditional way.
EDIT: A point for the "shortness and readability" view.
I was debugging some old code and stumbled across this:
fdsUnreportedMessages.Add(CreateFluentXml
.UTF8
.AddChild('LogEntry')
.AddChild('Time', Now)
.AddSibling('Severity', msg.MsgID)
.AddSibling('Message', msg.MsgData.AsString)
.AsString);
I knew immediately what the code does. If, however, the code would look like this (and I'm not claiming that this even compiles, I just threw it together for demo):
var
xmlData: IXMLNode;
xmlDoc : IXMLDocument;
xmlKey : IXMLNode;
xmlRoot: IXMLNode;
xmlDoc := CreateXMLDoc;
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction('xml',
'version="1.0" encoding="UTF-8"'));
xmlRoot := xmlDoc.CreateElement('LogEntry');
xmlDoc.AppendChild(xmlRoot);
xmlKey := xmlDoc.CreateElement('Time');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(FormatDateTime(
'yyyy-mm-dd"T"hh":"mm":"ss.zzz', Now));
xmlKey.AppendChild(xmlData);
xmlKey := xmlDoc.CreateElement('Severity');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(IntToStr(msg.MsgID));
xmlKey.AppendChild(xmlData);
xmlKey := xmlDoc.CreateElement('Message');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(msg.MsgData.AsString);
xmlKey.AppendChild(xmlData);
fdsUnreportedMessages.Add(xmlKey.XML);
I would need quite some time (and a cup of coffee) to understand what it does.
EDIT2:
Eric Grange made a perfectly valid point in comments. In reality, one would use some XML wrapper and not DOM directly. For example, using OmniXMLUtils from the OmniXML package, the code would look like that:
var
xmlDoc: IXMLDocument;
xmlLog: IXMLNode;
xmlDoc := CreateXMLDoc;
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction(
'xml', 'version="1.0" encoding="UTF-8"'));
xmlLog := EnsureNode(xmlDoc, 'LogEntry');
SetNodeTextDateTime(xmlLog, 'Time', Now);
SetNodeTextInt(xmlLog, 'Severity', msg.MsgID);
SetNodeText(xmlLog, 'Message', msg.MsgData.AsString);
fdsUnreportedMessages.Add(XMLSaveToString(xmlDoc));
Still, I prefer the fluent version. [And I never ever use code formatters.]
Compiler issues:
If you're using interfaces (rather than objects), each call in the chain will result in a reference count overhead, even if the exact same interface is returned all the time, the compiler has no way of knowing it. You'll thus generate a larger code, with a more complex stack.
Debugging issues:
The call chain being seen as a single instruction, you can't step or breakpoint on the intermediate steps. You also can't evaluate state at intermediate steps.
The only way to debug intermediate steps is to trace in the asm view.
The call stack in the debugger will also not be clear, if the same methods happens multiple times in the fluent chain.
Runtime issues:
When using interfaces for the chain (rather than objects), you have to pay for the reference counting overhead, as well as a more complex exception frame.
You can't have try..finally constructs in a chain, so no guarantee of closing what was opened in a fluent chain f.i.
Debug/Error logging issues:
Exceptions and their stack trace will see the chain as a single instruction, so if you crashed in .DoSomething, and the call chain has several .DoSomething calls, you won't know which caused the issue.
Code Formatting issues:
AFAICT none of the existing code formatters will properly layout a fluent call chain, so it's only manual formatting that can keep a fluent call chain readable. If an automated formatter is run, it'll typically turn a chain into a readability mess.
Are there any compiler issues?
No.
Are there any debugging issues?
Yes. Since all the chained method calls are seen as one expression, even if you write them on multiple lines as in the Wikipedia example you linked, it's a problem when debugging because you can't single-step through them.
Are there any runtime/error handling issues?
Edited: Here's a test console application I wrote to test the actual Runtime overhead of using Fluent Interfaces. I assigned 6 properties for each iteration (actually the same 2 values 3 times each). The conclusions are:
With interfaces: 70% increase in runtime, depends on the number of properties set. Setting only two properties the overhead was smaller.
With objects: Using fluent interfaces was faster
Didn't test records. It can't work well with records!
I personally don't mind those "fluent interfaces". Never heard of the name before, but I've been using them, especially in code that populates a list from code. (Somewhat like the XML example you posted). I don't think they're difficult to read, especially if one's familiar with this kind of coding AND the method names are meaningful. As for the one long line of code, look at the Wikipedia example: You don't need to put it all on one line of code.
I clearly remember using them with Turbo Pascal to initialize Screens, which is probably why I don't mind them and also use them at times. Unfortunately Google fails me, I can't find any code sample for the old TP code.
I would question the benefit of using "fluent interfaces".
From what I see, the point is to allow you to avoid having to declare a variable. So the same benefit the dreaded With statement brings, with a different set of problems (see other answers)
Honestly I never understood the motivation to use the With statement, and I don't understand the motivation to use fluent interfaces either. I mean is it that hard to define a variable ?
All this mumbo jumbo just to allow laziness.
I would argue that rather than increase readability it, which at first glance it seems to do by having to type/read less, it actually obfuscates it.
So again, I ask why would you want to use fluent interfaces in the first place ?
It was coined by Martin Fowler so it must be cool ? Nah I ain't buying it.
This is a kind of write-once-read-never notation that is not easy to understand without going through documentation for all involved methods. Also such notation is not compatible with Delphi and C# properties - if you need to set properties, you need to rollback to using
common notations as you can't chain property assignments.

Is Delphi "with" keyword a bad practice?

I been reading bad things about the with keyword in delphi but, in my opinion, if you don't over use it. It can make your code look simple.
I often put all my TClientDataSets and TFields in TDataModules. So in my forms I had code like this
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
with LongNameDataModule do
begin
LongNameTable1.Insert;
LongNameTable1_Field1.Value := "some value";
LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
LongNameTable1.Post;
end
end;
without the with keyword I have to write the code like this
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
LongNameDataModule.LongNameTable1.Insert;
LongNameDataModule.LongNameTable1_LongNameField1.Value := "some value";
LongNameDataModule.LongNameTable1_LongNameField2.Value :=
LongNameDataModule.LongNameTable2_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField3.Value :=
LongNameDataModule.LongNameTable3_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField4.Value :=
LongNameDataModule.LongNameTable4_LongNameField1.Value;
LongNameDataModule.LongNameTable1.Post;
end;
I think is easier to read using the with keyword.
Should I avoid using the with keyword?
The biggest danger of with, outside of pathological conditions like "with A, B, C, D" is that your code can silently change meaning with no notice to you. Consider this example:
with TFoo.Create
try
Bar := Baz;
DoSomething();
finally
Free;
end;
You write this code knowing that Bar is a property of TFoo, and Baz is a property of the type containing the method which has this code.
Now, two years later, some well-meaning developer comes in adds a Baz property to TFoo. Your code has silently changed meaning. The compiler won't complain, but the code is now broken.
The with keyword is a nice feature for making your code more readable but there are some pitfalls.
Debugging:
When using code like this:
with TMyClass.Create do
try
Add('foo');
finally
Free;
end;
There is no way to inspect the properties of this class, so always declare a variable and use the with keyword on that.
Interfaces:
When creating an interface in the with clause it lives till the end of your method:
procedure MemoryHog;
begin
with GetInterfaceThatTakes50MBOfMemory do
Whatever;
ShowMessage('I''m still using 50MB of memory!');
end;
Clarity
When using a class in a with clause that has properties or method names that already exists within the scope, it can fool you easily.
with TMyForm.Create do
Width := Width + 2; //which width in this with is width?
Of course when having duplicate names, you're using the properties and methods of the class declared in your with statement (TMyForm).
The with statement has its place but I have to agree that overuse can lead to ambiguous code. A good rule of thumb is to make sure the code is "more" readable and maintainable after adding the with statement. If you feel you need to add comments to explain the code after adding the statement then it is probably a bad idea. If the code is more readable as in your example then use it.
btw: this was always one of my favorite patterns in Delphi for showing a modal window
with TForm.Create(nil) do
try
ShowModal;
finally
Free;
end
I tend towards baning the with-statement altogether. As previously stated, it can make things complicated, and my experience is that it will. Many times the debugger want evaluate values because of withs, and all to often I find nested withs that lead to code that hard to read.
Brian's code seems readable and nice, but the code would be shorter if you just typecast the sender directly, and you remove all doubt about that component you enable:
TAction(Sender).Enabled := Something;
If you are concerned about typing to much, I prefare to make a temporary referance to the long-named object:
var
t: TTable;
begin
t := theLongNamedDataModule.WithItsLongNamedTable;
t.FieldByName(' ');
end;
I can't se why typing should bother you, though. We Are Typists First, Programmers Second, and code-completion, copy-paste and key-recording can help you be a more effective typist.
update:
Just stumbled over an long article with a little section on with-statements: he with keyword. The most hideous, dangerous, blow-your-own-feet-off feature in the language. :-)
When I first began pascal programming (with TurboPascal!) and learnt as I went, WITH seemed wonderful. As you say, the answer to tedious typing and ideal for those long records. Since Delphi arrived, I've been removing it and encouraging other to drop it - neatly summed-up by Verity at the register
Apart from a reduction in readability there are two main reasons why I'd avoid it:
If you use a class then you dont need it anyway - only records 'seem' to benefit from it.
Using the debugger to follow the code to the declaration with Ctrl-Enter doesnt work.
That said, for readability I still use the syntax:
procedure ActionOnUpdate( Sender : TObject )
begin
With Sender as TAction do
Enabled := Something
end;
I've not seen a better construct.
Your example, of a datamodule access within a button click, is a poorly contrived example in my opinion. The whole need for WITH goes away if you move this code into the data module where it should be. The OnClick then just calls LongNameDataModule.InsertStuff and there is no with needed.
With is a poor device, and you should look at your code to see why you are needing it. You probably did something wrong, or could do it a better way.
As Vegar mentioned, it's just as neat and much more readable, easier to debug, and less prone to stealth issues to use a temporary reference.
So far, I have never found a need to use with. I used to be ambivalent over it, until I took over a project that used the mind bending double with frequently. Questioning whether the original developer intended to reference items in the first with or second, if that ambiguous reference was a with-slip or clumsy code, the torment of trying to debug it, and the knock on effects of extending or modifying classes that use these abominations is just not worth anyone's time.
Explicit code is simply more readable. This way you can have your cake and enjoy eating it.
procedure TMyForm.AddButtonClick(Sender: TObject);
var
dm: TLongNameDataModuleType
begin
dm:=LongNameDataModule;
dm.LongNameTable1.Insert;
dm.LongNameTable1_Field1.Value := "some value";
dm.LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
dm.LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
dm.LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
dm.LongNameTable1.Post;
end;
I'm a firm believer of removing WITH support in Delphi. Your example usage of using a datamodule with named fields is about the only instance I could see it working out. Otherwise the best argument against it was given by Craig Stuntz - which I voted up.
I just like to point out that over time you may eventually (should) rmeove all coding in OnClick events and your code will also eventually migrate away from named fields on datamodules into using classes that wrap this data and the reason to use WITH will go away.
Your question is an excellent example of 'a hammer is not always the solution'.
In this case, 'with' is not your solution: You should move this business logic out of your form into your datamodule.
Not doing so violates Law of Demeter like mghie (Michael Hieke) already commented.
Maybe your example was just illustrative, but if you are actually using code like that in your projects, this is what you should do in stead:
procedure TLongNameDataModule.AddToLongNameTable1(const NewField1Value: string);
begin
LongNameTable1.Insert;
LongNameTable1_Field1.Value := NewField1Value;
LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
LongNameTable1.Post;
end;
And then call it from your form like this:
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
LongNameDataModule.AddToLongNameTable1('some value');
end;
This effectively gets rid of your with statement, and makes your code more maintainable at the same time.
Of course surrounding Delphi strings with single quotes will help making it compile as well ;-)
The main problem with "with" is that you don't know where its scope ends, and you could have multiple overlapping with statements.
I don't think you should avoid using it, as long as your code is readable.
One of the proposals to make it more readable (and less confusing in longer code) was if codegear added the option to allow for aliases in with, and probably allowing multiple withs in one:
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
with LongNameDataModule as dm, dm.LongNameTable1 as t1, dm.LongNameTable2 as t2 do
begin
t1.Insert;
t1.FieldByName('Field1').AsString := 'some value';
t1.FieldByName('Field2').AsString := t2.FieldByName('Field2').AsString;
t1.Post;
dm.Connection.Commit;
end
end;
As far as I'm concerned, With is quite acceptable in the case you give. It certainly improves the code clarity.
The real evil is when you have multiple with's open at once.
Also, my opinion is that what you are using the with on makes a big difference. If it's a truly different object then the with is probably a bad idea. However, I dislike having a lot of variables at one level even when this makes sense--generally data objects that hold an entire very complex data item--generally the entire piece of work the program is designed to work with. (I do not think this case would occur in an app that didn't have such an item.) To make the world clearer I often use records to group related items. I find that almost all withs I use are for accessing such subgroups.
There are many excelent answers here as to why the with statement is bad, so I'll try not to repeat them. I've been using the with statement for years and I'm very much starting to shy away from it. This is partially beause it can be difficult to work out scope, but I've been starting to get into refactoring lately, and none of the automated refactorings work withing a with statement - and automated refactoring is awesome.
Also some time ago I made a video on why the with statement is bad, it's not one of my best works but Here it is
Use with only temporarily (just as you comment-out temporarily).
It helps you write code sketches to get something compiled and running fast. If you consolidate the solution, clean it up! Remove with as you move code to the right place.
The current With statement is "dangerous", but it can be substantially improved:
With TForm1.Create (Nil) Do // New TForm1 instance
Try
LogForm ("); // That same instance as parameter to an outer method
"ShowModal; // Instance.ShowModal
Finally
"Free; // Instance.Free
End;
My proposal is:
No more than one object/record per With header.
Nested Withs not allowed.
Usage of " to indicate the object/record (double quotes are similar
to the ditto mark: http://en.wikipedia.org/wiki/Ditto_mark).

Is it safe to remove and reassign events this way? If not, why?

A.Event1 := nil;
A.Event2 := nil;
try
...
finally
A.Event1 := MyEvent1;
A.Event2 := MyEvent2;
end;
Can something go wrong with it?
EDIT:
I've accepted Barry's answer because it answered exactly what I asked, but Vegar's answer is also correct depending on the scenario, sadly I can't accept both.
This sounds like an event-nightmare I have seen before :-)
Instead of removing the events, I usually set a flag that I check in the event. I often use a integer rather than boolean so that the same flag can be set multiple times in one processing.
Something like this:
procedure TMyObject.Traverse;
begin
inc(FTraverseFlag);
try
...
finally
dec(FTracerseFlag);
end;
end;
procedure TMyObject.OnBefore( ... );
begin
if FTraverseFlag > 0 then
exit;
...
end;
I guess this easily could be made thread-safe to solve Barrys concerns.
It entirely depends on what happens in the bit of code marked '...'. If it e.g. starts up a background thread and tries to invoke Event1 or Event2 after execution has continued into the finally block, you may get unexpected results.
If the code is entirely single-threaded, then yes, neither Event1 nor Event2 should be triggered while the code is between the try and finally.
However, that does assume that Event1 and Event2 properties (all Delphi events are properties of a method pointer type) do not do unusual things in their setters. A pathologically malicious event setter could squirrel away a method pointer, and still be able to invoke it, even after you later call the setter with 'nil' as the value.
But that would be highly unusual behaviour.
As Barry said, the only real concern is with multithreaded concerns - other than that is perfectly normal. As VCL events setters just assign the event, nothing need to be worried.
If it is multithreaded you need to make operation atomic. Disabling several event handlers opens possibility that they are running at the moment then they are being disabled. Or Event2 starts when Event1 is being set to nil. All kinds of malfunctions may happen if these events called often. Possible solution to use semaphores instead. But then you may need to add extra code to event handlers as well.
Any way setting event handler temporarily to nil looks like a bad design. It will be incomprehensible very soon and hard to make do what it have to do any way. So you’d better spend some time and develop something more sophisticated.

Resources