@derek.jhon.evans
Thanks for your replys. You used one word, "neither", to ask my question, and then 2 posts to submit sugerences that implicates change the way how the existing application manage the data. Im sure your methods are better, but i still have no clue why neither of the proposed ways is good and why.
PS Methods proposed are simple ways to guarantee that any issue openning the file will be catched, and the file will be close at finish, without crash the app.
@derek.jhon.evans
You used one word, "neither", to ask my question, and then 2 posts to submit sugerences that implicates change the way how the existing application manage the data. Im sure your methods are better, but i still have no clue why neither of the proposed ways is good and why.
Well, OK. In general, try/except blocks should only be used to "catch and raise". So, your first example should be:
procedure RunTest;
var
LFile: TextFile;
begin
Assignfile(LFile, 'test.dat');
Reset(LFile);
try
{do stuff with file}
finally
CloseFile(LFile);
end;
end;
And you should call RunTest() with.
try
RunTest;
except
ON E: Exception do ToLog('Error Handling');
end;
Note how I've moved the exception "catch" outside the procedure itself. That means RunTest() does not define how exceptions are handled, and therefore it makes the implementation reusable across projects. Note, how I also, don't re-raise the exception since I'm happy that it has been handled, but If I wanted to, I could without creating a file handle leak. Bear in mind, the ToLog() could also raise an exception, which would cause problems in your examples.
Your second example has the same problem of catching exceptions inside what should be a generic reusable function. In the event, someone adds a "raise" command to your exception catch, then the closefile() will be skipped. For simple functions, its easy to see the issue. For larger programs, its easy to miss.
So, the
first rule of thumb is, when ever a non-managed resource is allocated, you _must_ add try/finally blocks. ie:
Reset(LFile);
try
{do stuff with file}
finally
CloseFile(LFile);
end;
The
second rule is to place the code for {do stuff with file} into its own procedure. This prevents the try/finally from becoming obscured by the "stuff". It also adds extra functionality by allowing code to use any file handle. ie: Input/Output or in the case of TSteam, compression, encryption, memory, network, etc streams.
And the
third rule is to catch exceptions outside of the "functionality" code. Exceptions were created as an improved way to pass errors back to calling functions.
Follow these guidelines and you will generate clear, concise & bulletproof source code.
Edit: Also note, Pascal file commands arnt guaranteed to raise exceptions, so IOResult should be checked. But, I think Ive said enough :-)