Try Catch Finally

Xojo supports the use of exceptions and the error handling machnisms that makes possible.

in order to use exceptions effectively you need to use a language feature called a Try block. It has several parts to it. First there is the initial TRY statement which opens a new scope level AND delimits where the TRY block starts. Its entirely possible to simply have code like

TRY
   // some code enclosed by the block
END TRY

You are not forced to have a CATCH statement in a try block. This style can be useful if, for instance, in the try portion you assign a value to a variable when there is no exception raised and then check that variable after the block and behave accordingly. Perhaps something like

dim f as Folderitem
TRY
   f = SpecialFolder.ApplicationData.Child("my.app.bundleID")
END TRY

if f is nil then
   f.CreateAsFolder
end if

But not that this code _could_ have an issue of for some reason SpecialFolder.ApplicationData is nil. We didnt check that and should before just blindly using it. There are other ways to accomplish much the same task by dealing with whatever exceptions are raised. For instance you might rewrite the above code to

dim f as Folderitem
TRY
   f = SpecialFolder.ApplicationData
   f = f.Child("my.app.bundleID")
CATCH nilError as NILObjectException
   // hmmm this means SpecialFolder.ApplicationData is nil ?
   // we might show an error dialog to the user or something to 
   // let them know that the folder we were trying to create cant be 
   // created in the SpecialFolder.ApplicationData location 
   // and we might return here rather than try to carry on
END TRY

if f is nil then
   f.CreateAsFolder
end if

This style at least makes it so we have checked whether or not SpecialFolder.ApplicationData was nil – its unusual that it might be but can happen.

You can have as many CATCH statements as you want and they can be written in many different styles. Personally I always use the form

Catch ErrorParameter As ErrorType

with a name for the error parameter; which actually ends up being a local variable in the CATCH code you write, and a specific type. In my code you might see

TRY
CATCH noExc as NilObjectException
  // code to deal with the Nil Object Exception
CATCH ioExc as IOEXception
  // code to deal with the IO Exception
END TRY

and specific code where noted by the comments to deal with the situation. I do not recommends using a single catch with a long list of select statements using introspection etc to try and handle the various exceptions. The only time I might recommend that is when its the App.Unhandled exception event and you are trying to create a report that a user can send you. Even there you have to be careful of which exceptions you catch because a normally Quit application uses an exception to Quit normally.

The last part of a TRY CATCH block is the FINALLY block. This is code that runs after all the code in any TRY or CATCH sections executes. Some times there is code that you want to execute as part of clean up that needs to release memory, mutexes, semaphores etc.

However, some assume that it will ALWAYS execute regardless of what code you have in the TRY and CATCH portions. In some languages the code in the FINALLY block is ALWAYS executed. This is NOT the case in Xojo and, if you’re not careful, it CAN easily be skipped.

For instance, if you use RETURN as the last line of the TRY or a CATCH block that is executed the FINALLY block WILL be skipped.


Try
  Raise New NilObjectException
Catch
  Return
Finally
  Break
End Try

If you execute this code you will see that the BREAK in the finally block is NOT executed. And if you changed this to


Try
  Return
Catch
Finally
  Break
End Try

Again you will see the break in the finally clause is not executed. So be careful about the use of return in a TRY CATCH block IF you expect the FINALLY clause to always be executed.

The Law of Demeter

Recently I re-read The Pragmatic Programmer mostly while on a break in Mexico. I also did my fair share of sitting in the sun, eating and event drinking but I read a LOT as well.

And I keep learning, or at least reminding myself, of several things I think are really useful to all of us.

In terms of writing OOP code the Law Of Demeter is one that is really useful. Basically in this Law you should only access :

– items (properties, methods, constants, etc) of the of the object you are part of
– items (properties, methods, constants, etc) you are passed as parameters
– items (properties, methods, constants, etc) of objects you create in your code

This limits the knowledge your code needs of the internals of other objects.

Suppose we have a set up something like :

Global Dim someGlobalVar as integer

Class FooBar
   Dim i as integer
   Sub fubaz() as string
   End Sub
End Class

Class Bar
   Dim fubar as FooBar
   Sub Constructor()
     fubar = new FooBar
   End Sub 
 
   Sub Baz()
   End Sub
End Class

Class Foo
  Dim BarInstance as Bar

  Sub Constructor
    self.BarInstance = new Bar
  End Sub

  Function HasInstance() as Boolean
    // this one is OK !!!!!
    return (BarInstance is nil) = false   
  End Function

  Sub CallBazOfBar()
    // this one is OK !!!!!
    BarInstance.Baz()
  End function

  Function CallBazOfPassedInBar(b as Bar)
    // this one is OK !!!!!
    b.Baz()
  End Function

  Function CreateAndCallBazOfBar()
    // this one is OK !!!!!
    dim b as new Bar
    b.Baz()
  End Function

  Function ReachesThroughBarToFooBar() as integer
    return BarInstance.fubar.i
  End function

  Function ReliesOnGlobal() as integer
    return someGlobalVar
  End function

  
End Class 

Then for us to adhere to this principle the following new methods on our Class Foo would NOT be ok :

Function ReachesThroughBarToFooBar() as integer
   return BarInstance.fubar.i
End function

This one is NOT ok because it requires the Foo class to know more about the internals and implementation of the Bar class AND FooBar class than it should. Instead the Bar class should have a method on it that can be invoked to get details of its properties or classes it owns.

Function ReliesOnGlobal() as integer
   return someGlobalVar
End function

This one is NOT ok because it requires the Foo class to rely on a global variable that is outside the scope of the instance and the method using it.

Methods in our Foo class should ONLY use :

  1. methods in the instance itself (HasInstance is OK)
  2. methods of any parameters passed to the methods like CallBazOfPassedInBar(b as Bar)
  3. Any objects created/instantiated within the method like CreateAndCallBazOfBar
  4. methods in the instances properties (in this case methods of Bar like CallBazOfBar)
  5. A global variable, accessible by the instance, that is in the scope of the method (this last one is harder to explain)

I like the Wikipedia summary which is

 For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as “use only one dot”. That is, the code a.b.Method() breaks the law where a.Method() does not.

https://en.wikipedia.org/wiki/Law_of_Demeter

When Apple does its own thing

I started up Xojo 2019r3 the other day and changed some colors while tracking down a nifty dark mode bug (see http://feedback.xojo.com/case/58695)

And after that all versions of Xojo would, when starting, immediately show the color picker panel like this :

Now lets be clear – I dont consider this to be a Xojo bug.

It seems that, Apple writes their own keys to the Xojo plist and these may influence whether the color picker panel shows up when you start Xojo.

If you open the Xojo plist in a text editor you may find that you have a bunch of keys like  NSColorPanelMode, NSColorPanelMode.modal, NSColorPanelToolbarIsShown.modal, NSColorPanelVisibleSwatchRows.modal, NSSplitView Subview Frames, NSColorPanelSplitView, NSToolbar Configuration com.apple.NSColorPanel. NSWindow Frame NSColorPanel, and NSWindow Frame NSColorPanel.modal

Apple adds these to the plist on its own (personally I find this less than helpful but there’s really no arguing with Apple about this sort of thing)

What I dont know is if Xojo can/could make sure that the color panel preferences get writtem in a way the color picker does not open on next launch or not.

If they can it would sure be nice.

In the mean time I’ve simply stripped those keys out when/if they appear and things go back to normal.

Really ?

This is so annoying. I have no bluetooth mouse powered on but I do have a USB one and it works fine. And the mouse control panel says it cannot find it so I cannot change the tracking speed. System Report knows there’s a mouse connected as you can see.

Turn the bluetooth mouse on and the panel finds that and now I can adjust the tracking speed. But it doesn’t affect the USB mouse – which is still connected and working (the bluetooth mouse is literally upside down on my desk untouched)

No. I don’t want a wireless mouse as I’m tired of my Magic mouse and “LOST CONNECTION”. Apparently Apple insists I use a wireless mouse,

Awesome !

= vs IS

A good question on the discord server I participate in prompted a good question. It started with IS and = are just synonyms right?

It turns out that MOST times this may be true. But not always. And that little “but not always” can get you in trouble if you dont know when the difference is important.

IS is always used to determined if one instance of a class refers to the exact same instance as another reference. You might want to reread my prior post about classes, instances and objects

And in many cases, but not all, = will give you the same result as using IS.

So code like

Dim d1 As New Class2
Dim d2 As New Class2

If d1 = d2 Then
  System.debuglog "d1 = d2 => true !"
Else
  System.debuglog "d1 = d2 => FALSE !"
End If

If d1 Is d2 Then
  System.debuglog "d1 IS d2 => true !"
Else
  System.debuglog "d1 IS d2 => FAlSE !"
End If

will usually put out debug log messages that say D1 = D2 => false from both checks.

This assumes that our class, Class2, does NOT implement operator_compare. And that is the caveat here. IF a class implements operator_compare the IS and = operators may not give the same result any longer.

Operator_compare is often used to compare the contents of a class – and not the references (although it doesnt have to compare contents since you can make it do whatever you want).

If we defined our class, Class2, like

Protected Class Class2
  Sub Constructor(contents as string)
    myContent = contents
  End Sub

  Function Operator_Compare(rhs as Class1) As integer
      If rhs Is Nil Then 
        Return -1
      End If
		  
      If Self.myContent < rhs.myContent Then
        Return -1
      End If
      If Self.myContent > rhs.myContent Then
        Return 1
      End If
		  
    Return 0
		  
  End Function

  Private myContent As String
End Class

Now our code above will give very different results because Operator_compare is used when the line

If d1 = d2 Then

is run. In this case it will call the custom operator_compare method and that compares the contents of two objects and NOT whether or not two objects references refer to the same object. However, the line

If d1 Is d2 Then

will ALWAYS determine if the two objects references refer to the same instance.

And now you know !

WAY off topic but so what ????

It is my blog and this is something I’ve been working at for months.

I PASSED my on snow certifications for the Canadian Ski Patrol and now get to do a few shifts working with more senior patrollers before they turn me loose and I can patrol on my own !

What an awesome way to spend New Years Day !!!!!!

And I would like to take the time to thank ALL of the instructors that have helped all of the candidates along. They have been really really great !

WeakRef usage

There was a good question from Markus in a recent comment on a different post of mine.

In children of a window we should keep track of the parent window by using WeakRef.
But what if I have a class cDepartment with a list of employees defined as Employees() as cEmployee – should that then better also be defined as WeakRef? And why or why not?

First I’ll say “it depends” as there’s certainly no single correct answer to such a question. In many cases it will depend on the expected usage.

WeakRefs are a curious thing. In Xojo most times you have a reference to an object its a strong reference. What happens is that the objects reference count is increased and only when that counter gets set to 0 will the object be destroyed.

For instance, if we have code like the following

Class Foo

  Sub Destructor()
    break
  End Sub

End Class


dim firstRef as Foo
dim secondRef as Foo

firstRef = new Foo 
// the object firstRef refers to now has a reference count of 1

secondRef = firstRef 
// since secondRef refers to the SAME object as firstRef
// the object firstRef refers to now has a reference count of 2

firstRef = nil
// the object firstRef refers to now has a reference count of 1

secondRef = nil
// the object firstRef refers to now has a reference count of 0
// and it will be destroyed and the breakpoint in the destructor
// will be encountered

Now what happens if we use a WeakRef instead for secondRef ? If we turn that code into the following

Class Foo

  Sub Destructor()
    break
  End Sub

End Class


Dim firstRef As Foo
dim secondRef as Foo
Dim weakSecondRef As WeakRef // <<<<<<< note the type !

firstRef = New Foo 
// the object firstRef refers to now has a reference count of 1

weakSecondRef = New WeakRef(firstRef)
// since weakSecondRef is a WeakRef the object 
// firstRef refers does NOT increment its reference count

firstRef = Nil
// the object firstRef refers to now has a reference count of 0
// and it will be destroyed and the breakpoint in the destructor
// will be encountered now

// but what about weakSecondRef's contents ???
// lets fetch that value and see whats in there now
secondRef = Foo(weakSecondRef.Value)

break // <<< here you will find that the returned value is NIL !

And if you try to use the object contained by the weakref secondRef you will find that it is nil. A weakref allows an object to be referenced in a way that it does not increment the original objects reference count which CAN let that object be nil’d in other code.

When you use a weakref you MUST check the VALUE of the weakref to see if what you get back is NIL because the object may have been set to nil elsewhere.

Now that we have the basics of weakrefs out of the way lets turn back to Markus’ original and my original reply of “it depends”.

n children of a window we should keep track of the parent window by using WeakRef.

Indeed you may want to have child windows retain a weakref to refer to a parent window. It would allow you to close the parent and not the child, as the weakref will not increment the reference count of the parent window. But, you may want the parent to not be set to nil when there are child windows.

This decision will depend entirely on how your UI is supposed to work. If those child windows should not exist without a parent then a hard reference to the parent may make perfect sense.

But what if I have a class cDepartment with a list of employees defined as Employees() as cEmployee – should that then better also be defined as WeakRef? And why or why not?

Again this will depend entirely on how the cDepartment class should behave. Can cEmployees be added & removed at runtime and should the cDepartment class be able to deal with this ? Or should cDepartment need to be reconstituted when such changes of its employees are made ? The correct behaviour isnt dictated by the underlying code and whether you should use weakrefs but by the needs of the application and how cDepartment should behave.

You could always use weakrefs but this could have unintended consequences for the cDepartment class as this would allows its cEmployees to be removed at runtime. If you had used a FOR EACH loop with an iterator to perform some function you would need to handle the exceptions that could be encountered. Iterators will be invalidated by removal of an employee while iterating over the list and will raise an exception of this occurs. Weakrefs would permit this. Hard references would not.

2019, The Lost Year, in review

2019 has been an interesting year to say the least.

Mine started off with the septic system needing to be replaced in the first week of January as the old system had been installed in a manner that it was not repairable and it had failed. So in the cold of January our yard was torn up and excavation work went on. One of our basement bedrooms had to have its floor cracked open and a new main line to the septic system installed. $25K later it was all back in working order and we just had landscaping to fix up.

Awesome start !

Work on Xojo 2019r1 was progressing when I was suddenly let go in March.

I panicked a bit. But things have worked out well for me so far and I’m happy doing what I’m doing for a really great group of clients. Since then I’ve created 300+ Feedback reports.

Xojo 2019r1 was released in April and thats the last release that I really contributed much to. 2019r1.1 went out in May.

Betas for Xojo 2019r2 started shortly after that and this brought API 2.0 and a fair number of bugs and complaints along with it. Especially aggravating were changes to many property names, method names and event names. Event names proved to be the most difficult for developers of all sorts, especially in the third party arena, to deal with. For my uses it was a beta that was going along fine until API 2.0 hit then it made it clear that my clients projects were NOT going to transition easily so I more or less stopped testing entirely.

Xojo 2019r2 was released in Oct. There was more angst expressed about the renames by users that were not part of the beta program.

About this time I started taking training to be a Ski Patroller. I’d thought about going and getting certified as a ski instructor again but Ski Patrol made more sense.

2019r2.1 with a number of bugs fixes followed in Nov. Of significant note 2019r2 was pulled from further distribution and 2.1 reverted the changes to event names. This was a welcome reversion. I think a number of people were surprised that Xojo took this course of action. I really didnt test much in this release.

Shortly after, in Dec, 2019r3 was shipped and it brought iOS dark mode along with it and a handful of other fixes that were not iOS related. Again since it did not contain a lot of fixes that were really relevant to my clients I mostly didnt test it and have only lightly used it.

And about this time I passed my written and diagnostic exams to progress on to the on snow training to be a Certified Canadian Ski Patroller. (YAY !!!!!!)

For some the year was a non-event as far as Xojo went. No new OOP features, classes, controls or other significant improvements were added. A lot of changes were made. But Xojo hasn’t become more stable, capable, or reliable as a result of those changes. Just different. It’s about the same as it always has been and several new bugs seemed to be a result of API 2.0 changes. While API 2.0 is out now it isn’t a game changer in most respects. At least not yet. It’s hard to know what else might come along in the future but the roadmap doesnt seem to have anything for API 2.0 further out beyond expanding to iOS. What remains is still things that have been on the to do list for several years like Web 2.0, Android, and plugins written in Xojo.

For me both personally and professionally it was a year with big changes in my personal life and professional life. For Xojo not so much.

How was your year ?

#if Targetxxxx

I’ve seen this a lot in posts on the forums and even in code submitted as part of bug reports

If TargetWindows Then
  // Windows only code not excluded from compilation.
End If

The code inside the if will only execute on Windows. However becuase this code is just a normal if it HAS to COMPILE on ALL targets even if the intention is that it only be used on Windows (which it obviously is)

If you intend some code to ONLY be used on Windows you’re better off to use this form

#If TargetWindows Then
  // Declares for example
#Endif

This code will ONLY exist in a Windows builds and so can ONLY execute on Windows. And, because it will only be used on Windows the compiler will ignore the code inside the #if … #endif on all other platforms so the code doesn’t even have to compile on macOS or Linux (which it would in the first example shown)

Usually when you see the first form you really want the second using #if

Next time you find yourself writing

if Target

reconsider if you really should be using #if instead

Classes, Instances and Objects

There’s a fun “theoretical question” on the forums.

What is the relationship between a class, object, and instance?

Lets see if I can help any (or maybe just confuse the heck out of folks even more)

In Xojo in the IDE when you define a CLASS you are creating a “template” for how every item of this type will behave. You’re defining the properties, the methods, events etc etc etc. And EVERY item that IsA <this type I defined> returns true for IsA one of these.

AT runtime when you application runs and it uses the NEW operator to create a new item of this type you are creating new INSTANCES. Instances are the ACTUAL copies you create that you can manipulate at runtime.

And EVERY instance in Xojo IsA Object. Its the base object for EVERY dynamically created type where you use NEW to create one.

So CLASSES are a design time thing.

INSTANCES and OBJECTS are runtime things.