I’m busy refactoring and moving the code forward to API 2.
In converting LastError to the exception, I’m converting to Try … Catch … Finally … End Try. Just looking at best practice in a scenario such as this:
If f <> Nil And Not f.Exists Then
theTOS = TextOutputStream.Create(f)
If theTOS.LastErrorCode <> 0 Then
MsgBox "Can't create safe temporary list file."
Return Nil
Else
If defaultEntry <> "" Then
theTOS.Write defaultEntry + EndOfLine.UNIX
Else
theTOS.Write "" + EndOfLine
End If
theTOS.Flush
theTOS.Close
End If
End If
In the conversion, which is the better path:
If f <> Nil And Not f.Exists Then
Try
theTOS = TextOutputStream.Create(f)
Catch e As NilObjectException
MsgBox "Can't create safe temporary list file."
Return Nil
Catch e As IOException
// Permissions issue?
Finally
If defaultEntry <> "" Then
theTOS.Write defaultEntry + EndOfLine.UNIX
Else
theTOS.Write "" + EndOfLine
End If
theTOS.Flush
theTOS.Close
End Try
End If
Or
If f <> Nil And Not f.Exists Then
Try
theTOS = TextOutputStream.Create(f)
Catch e As NilObjectException
MsgBox "Can't create safe temporary list file."
Return Nil
Catch e As IOException
// Permissions issue?
End Try
If defaultEntry <> "" Then
theTOS.Write defaultEntry + EndOfLine.UNIX
Else
theTOS.Write "" + EndOfLine
End If
theTOS.Flush
theTOS.Close
End If
If you’ve got an IOException, something went wrong with creating the file and you can’t use theTOS. Trying to write in the finally block (or just afterwards) is going to raise another exception, so you want to catch the exception after you’re done writing.
Really simply, written in the forum editor:
try
theTOS = TextOutputStream.Create(f)
theTOS.Write("stuff")
theTOS.Close
catch ex as IOException
// Something bad happened, tell the user or do something safe within a thread
end try
myself using also a boolean in return if the method was executed fine or flase if there was an error. its useful to handle the program flow.
as example
var f As FolderItem = GetTemporaryFile()
if SaveFile(f) = True then
else
endif
instead of messagebox please use a error window with a list
or every error a messagebox popup dialog would annoying the user when a method was called in a loop 100 times.
xojo have also a simplified error handling i found a excel docu, its useful too Exception err As OLEException
Finally is usually used for freeing resources created in the Try block.
I feel like the TextOutputStream.Close call should go in “finally”. Because if the IOException happens during the write operation, the stream should still be closed. theTOE should still be checked for Nil before use.
I would probably tend to put a try/catch around each separate action. All my database activity is inside wrapper methods, where I check for and log errors.
Ideally, TextOutputStream.Close would be implemented such that it doesn’t throw exceptions since it is supposed to free resources. I don’t know if that’s how it’s implemented in Xojo, however. If Close does have the possibility of raising exceptions, it would potentially lead to memory leaks.
A nice feature in the documentation for Xojo would be documentation of all possible exceptions for each method.
Finally is used for code that needs to run even if an exception occurred earlier in the method. For example, when using a Semaphore:
Dim lock As New Semaphore
lock.Signal()
Try
// do things that might raise an exception
Finally
lock.Release()
End Try
Without a Try...Finally construct, exceptions raised after the Semaphore is signaled would prevent it from ever being released, and any other threads that are waiting on the Semaphore would deadlock.
This is the problem with Exceptions - you don’t know what can throw one.
Documenting them would be a start but even that isn’t a very good solution as what can throw an exception or the exceptions thrown could change between versions.
A much better solution would be if there were some kind of Checked Exceptions implementation that at least got the compiler to throw warnings if exceptions were not being handled.
Following the design logic that you are all sharing and testing, this is what I’ve settled on:
If f <> Nil And Not f.Exists Then
Try
theTOS = TextOutputStream.Create(f)
If defaultEntry <> "" Then
theTOS.Write defaultEntry + EndOfLine.UNIX
Else
theTOS.Write "" + EndOfLine
End If
theTOS.Flush
Catch e As IOException
// Permissions issue?
Finally
theTOS.Close
End Try
End If
If theTOS is nil at the Create line, the Finally block also gets executed (as it’s always executed whether you got an exception or not) and theTOS.Close raises a NilObjectException, this time, unhandled.
Check if it’s nil and you’re set.
If f <> Nil And Not f.Exists Then
Try
theTOS = TextOutputStream.Create(f)
If defaultEntry <> "" Then
theTOS.Write defaultEntry + EndOfLine.UNIX
Else
theTOS.Write "" + EndOfLine
End If
theTOS.Flush
Catch e As IOException
// Permissions issue?
Finally
If theTOS <> Nil Then
theTOS.Close
End If
End Try
End If