More good habits

On the forum there was a suggestion that a person should use a container control that had a few controls embedded in it at design time. And then when using that container control that they should skip providing an API that the container presented and just reach inside the container and manipulate the controls it contain directly.

Personally I would recommend against this.

I’d start by saying when you create a container control ALL the controls in it should be private by default to prevent this. And that if you want to expose functionality of the controls on the container you do so by defining methods and events on the container that any code OUTSIDE the container can call or react to just as if the container control was any other single control and not a composite one like it is.

Why would I make such a recommendation ?

  1. good habits
  2. encapsulation
  3. reusability
  4. long term flexibility and maintainability

The first point is just that this is a good habit to get into. And the reason its a good habit is because of points 2, 3 and 4. Properly encapsulating and hiding the details from other bits of your code is a good thing. Code outside the container doesnt need to know HOW the container does what it does. Just that it does what is expected when you call its methods, change its properties and react to the events it exposes. Thats it. It should be a black box like the built in Xojo listbox, pushbutton, or any other built in control is. You dont need to know how those do what they do, just that they do what you expect when you call the methods, set the properties and react to their events.

And the bonus to doing this is that it makes the likelihood you, or others, can reuse your control in more places in your project or in other projects much higher because the control is self contained.

Long term it also lets you do things like completely swap out the implementation of the container for some other means and as long as you dont need to change the API nothing outside the container control even needs to be aware this has happened. This makes your own code easier to maintain since you no longer have to look through all the code outside of the container to know if you also need to alter it because something in the container changed.

These are all good things regardless of whether this code is for your own use, more general distribution or possibly for sale or to give away.

I’d encourage everyone to keep these things in mind when ever they write their own custom controls.

Code for safety II

Back when I wrote Code for Safety I gave one example of something that I’m sure we’ve all done from time to time. Saving the state of some flag and then returning and having possibly multiple places to reset the flag we saved.

There’s another thats is more common with the advent of HiDPI support for Windows; drawing in a listbox event like CellBackGroundPaint Saving the graphics state, disabling antialiasing, and then needing to restore that state.

This is especially true on Windows where you may need to disable anti-aliasing, change the foreground color & fill the background to achieve some custom effect. If you dont disable anti-aliasing you can end up with odd effects as noted in the documentation and this post.

Having a way to save the existing state and consisntenly and reliably restore it to what it was when the method was called is useful since you dont know if the graphics object is passed on to other events like CellTextPaint. Not restoring the state may lead to unwanted side effects.

So how to make it so you can simply save the state and never worry about it being restored properly ? As I mentioned before ; a class that has almost nothing to it but a constructor & a destructor.

My implementation is called GraphicsStatePreserver.

The constructor is simply

Sub Constructor(g as graphics)
  mG = g
  
  Me.mAntiAlias = g.AntiAlias
  Me.mAntiAliasMode = g.AntiAliasMode
  Me.mBold = g.Bold
  Me.mCharacterSpacing = g.CharacterSpacing
  Me.mForeColor = g.ForeColor
  Me.mItalic = g.Italic
  Me.mLastPage = g.LastPage
  Me.mPenHeight = g.PenHeight
  Me.mPenWidth = g.PenWidth
  Me.mScaleX = g.ScaleX
  Me.mScaleY = g.ScaleY
  Me.mTextFont = g.TextFont
  Me.mTextSize = g.TextSize
  me.mtextunit = g.TextUnit
  Me.mTransparency = g.Transparency
  Me.mUnderline = g.Underline
  
End Sub

We save the current state of the various writeable properties of the graphics into locals, and a hard reference to the graphics object. We keep a hard reference to make sur it cannot go out of scope before we have done our thing to restore the various settings.

The destructor is equally simple

Sub Destructor()
  mg.AntiAlias = Me.mAntiAlias 
  mg.AntiAliasMode = Me.mAntiAliasMode 
  mg.Bold = Me.mBold 
  mg.CharacterSpacing = Me.mCharacterSpacing 
  mg.ForeColor = Me.mForeColor 
  mg.Italic = Me.mItalic 
  mg.PenHeight = Me.mPenHeight 
  mg.PenWidth = Me.mPenWidth 
  mg.ScaleX = Me.mScaleX 
  mg.ScaleY = Me.mScaleY 
  mg.TextFont = Me.mTextFont 
  mg.TextSize = Me.mTextSize 
  mg.textunit = Me.mTextUnit
  mg.Transparency = Me.mTransparency 
  mg.Underline = Me.mUnderline 
  
End Sub

When this class is destroyed it will put back all the properties on the graphics just as they were when the instance was created.

And since an instance is used like

Dim statepreserver As New GraphicsStatePreserver(g)

#If targetwindows
  g.AntiAlias = False
#EndIf

If row < 0 Then 
  Return True
End If
If column < 0 Then 
  Return True
End If

// whatever othe r code you need in cell background paint

Return True

This instance will ONLY go out of scope, and be destroyed, at the points where the event is being exited. And that happens to be the exact points we want to restore the graphics state.

Here’s the entire implementation

Class GraphicsStatePreserver
	Sub Constructor(g as graphics)
	  mG = g
  
	  Me.mAntiAlias = g.AntiAlias
	  Me.mAntiAliasMode = g.AntiAliasMode
	  Me.mBold = g.Bold
	  Me.mCharacterSpacing = g.CharacterSpacing
	  Me.mForeColor = g.ForeColor
	  Me.mItalic = g.Italic
	  Me.mLastPage = g.LastPage
	  Me.mPenHeight = g.PenHeight
	  Me.mPenWidth = g.PenWidth
	  Me.mScaleX = g.ScaleX
	  Me.mScaleY = g.ScaleY
	  Me.mTextFont = g.TextFont
	  Me.mTextSize = g.TextSize
	  me.mtextunit = g.TextUnit
	  Me.mTransparency = g.Transparency
	  Me.mUnderline = g.Underline
  
	End Sub

	Sub Destructor()
	  mg.AntiAlias = Me.mAntiAlias 
	  mg.AntiAliasMode = Me.mAntiAliasMode 
	  mg.Bold = Me.mBold 
	  mg.CharacterSpacing = Me.mCharacterSpacing 
	  mg.ForeColor = Me.mForeColor 
	  mg.Italic = Me.mItalic 
	  mg.PenHeight = Me.mPenHeight 
	  mg.PenWidth = Me.mPenWidth 
	  mg.ScaleX = Me.mScaleX 
	  mg.ScaleY = Me.mScaleY 
	  mg.TextFont = Me.mTextFont 
	  mg.TextSize = Me.mTextSize 
	  mg.textunit = Me.mTextUnit
	  mg.Transparency = Me.mTransparency 
	  mg.Underline = Me.mUnderline 
  
	End Sub

	Private Property mAntiAlias As boolean
	Private Property mAntiAliasMode As Graphics.AntiAliasModes
	Private Property mBold As boolean
	Private Property mCharacterSpacing As Integer
	Private Property mForeColor As color
	Private Property mG As graphics
	Private Property mItalic As boolean
	Private Property mLastPage As Integer
	Private Property mPenHeight As double
	Private Property mPenWidth As double
	Private Property mScaleX As double
	Private Property mScaleY As double
	Private Property mTextFont As string
	Private Property mTextSize As Single
	Private Property mtextunit As FontUnits
	Private Property mTransparency As double
	Private Property mUnderline As boolean

End Class

Why shadowing should be avoided

We’ll create a sample project to demonstrate why its a bad thing to do.

Start a new desktop project.

Add a new Class that is a subclass of ”CancelButton” by dragging a CancelButton from the library to the Navigator.

Name this new class “myPushButton”

Add a property  to it – enabled as boolean

Make sure the property is public

Now on Window1 add an instance of this new button subclass.

Name it “MyPb”

Now add a bevel button and name it bevTestSubclass.

Change its Caption to say “bevTestSubclass”

In its action event put

myPb.enabled = Not myPb.enabled
myPb.invalidate

Add a second bevel button and name it bevTestBaseClass

Change its Caption to say “bevTestBaseClass”

In its action put

PushButton(myPb).enabled = Not PushButton(myPb).enabled
PushButton(myPb).invalidate

Save (if you care to) and Run

If you push the bevTestBaseClass button the button enables & disables on each push. And it does this visibly.

But if you click the bevTestSubclass button nothing happens.

Why not ?

Properties are not virtual. Quite literally there are two “enabled” properties and they are not the same one. The custom subclass contains one. And the base class contains one.

So when the code knows you are referring to the subclass type the “Enabled” property that is used is the one in the subclass instance. And the framework doesn’t look at this one at all.

So the framework looks at the one in PushButton and redraws with whatever Enabled state that one says.

And its not the same as the one in the subclass.

But when you press the bevTestBaseClass button you do get the change you expected because the cast makes the code refer to the Superclass version of enabled.

This specific use where a cast is involved isn’t so hard to find with a search and replace. But it’s also not the only way that shadowed properties cause problems. The really tricky ones are where the declared type of a variable is the superclass type and then you get much the same behaviour as with the casts. And this one is NOT easy to find.

We’ll demonstrate by adding additional code to the project so far.

First lets define a new method – FlipSubClass – that takes a myPushbutton as a parameter.

Public Sub flipSubclass(button as myPushButton)
  button.enabled = Not button.enabled
  button.invalidate
End Sub

And for good measure we’ll add a new method – FlipSuperClass – that takes a Pushbutton as a parameter

Public Sub flipSuperClass(button as PushButton)
  button.enabled = Not button.enabled
  button.invalidate 
End Sub

The only difference between these two is the type of the parameter.

Now lets add two more bevel buttons to use these new methods.

Add a bevelbutton and name it bevDimSubClass and set the caption to bevDimSubClass.

In this bevel buttons action event put

  flipSubClass(myPb)

Add a second bevel button named bevDimSuperClass and set the caption to bevDimSuperClass

And in this action event put

  flipSuperClass(myPb)

And run.

Note this time there is NO explicit cast required and we can safely pass a myPushButton to a method that takes a PushButton because a subclass IS always also the super class type (isA would be true if you checked myPb isa PushButton)

And yet the bevDimSubclass button has no effect on the buttons appearance but the bevDimSuperClass button does.

Its the exact same issue as before but this time it’s even harder to detect because what natters here is not the actual type or the instance but the DECLARED type of the parameter. 

Since shadowing can cause such hard to track down bugs it better to avoid it.

Now IF you cannot and really to require a subclass have its own “Enabled” property that actually works you should add it as a COMPUTED PROPERTY that in the getter simply casts SELF to the super type and returns the’s supers property value. And in the getter again cast to the super type and set the supers property to that value given.

And here’s a sample that shows the bad version and how to make it work as expected

Follow up on what type am I ?

Back when I was still at Xojo I wrote a blog post about what type of variable am I ?

This is a follow up on that to maybe help explain things more.

The particular difficulty is arrays. They are simple and can cause deceptive an hard to find bugs BECAUSE they are so easy to use and the Xojo language appears to do what you intend (but I don’t think it is doing the wrong thing).

Its why its important to know the difference between a value type and a reference type.

The set up for this is simple. A new Class in a desktop project cleverly named Class1. That class has one public property, values() as variant.

The rest of the code is in the Window1.Open event in a desktop project.

It’s important that you turn on Preferences > Debugging > Show Object IDS in variable lists.

The rest of the code is simply this 

Dim theClassInstance As New class1

Dim emptyarray() As Variant

theClassInstance.values = emptyArray // <<< THIS LINE IS WHAT CAUSES THE HAVOC !!!!
// Because arrays are "reference types" this line does not copy each value in the 
// array into a new array
// it simply sets "theClassInstance.values" to refer to the same array as 
// "emptyarray" refers to
// so altering one looks like it alters the other

// for this example turn on Preferences > Debugging > Show Object IDS in variable lists

Break
// now look at the object ID of emptyarray and theClassInstance.values
// they _should_ be the same which means they are the same object so 
// changing one will appear to change the other

theClassInstance.values.append ( "123" )
Break
// now look at the object ID of emptyarray and theClassInstance.values
// they _should_ be the same which means they are the same object so 
// changing one will appear to change the other

Redim emptyarray(-1)
Break
// now look at the object ID of emptyarray and theClassInstance.values
// they _should_ be the same which means they are the same object so 
// changing one will appear to change the other

emptyarray.append ( "123" )
Break
// now look at the object ID of emptyarray and theClassInstance.values
// they _should_ be the same which means they are the same object so 
// changing one will appear to change the other

Redim theClassInstance.values(-1)
Break
// now look at the object ID of emptyarray and theClassInstance.values
// they _should_ be the same which means they are the same object so 
// changing one will appear to change the other

If you run this code at each break point you can see that if you check the array that was NOT touched in code you will see it has also changed to mimic the other.

This is because arrays are reference types and the line

        theClassInstance.values = emptyArray 

copies the REFERENCE – not the values in the array 

Be careful with your references out there !

An extensible class factory

Some times you want to make a nice generic class that a user can extend via subclassing.

However, one issue arises with this.

How can a factory method in the super class create instances of the subclasses ? This is especially troublesome if the classes you have are encrypted so you cant change the source or in a plugin.

However, it IS possible to create an “extensible factory method” so the factory can create instances of the subclasses users provide.

Lets look at how you can do this.

Usually a class factory method looks something like

Class MySuperClass
  Private Sub Constructor()
  End Sub

  Shared Function CreateNew()
    return new MySuperClass
  End Function
End Class

The private constructor makes it so no one can create an instance without using the factory.

So how do you make this basic pattern extensible so the factory can create instances of the correct subclasses ?

If you had the source code you could change the factory method to

  Shared Function CreateNew(name as string)
    select case name
    case “MyCustomSubclass”
       return new MyCustomSubclass
    else
      return new MySuperClass
    end select
  End Function

But there are some real problems with this

the superclass has to be alterable – if you dont have source code you cant do this. So distributing code to other people to uses becomes a real problem

every time you add a subclass you have to remember to alter the superclass

What do you do if this is a plugin written in C++ ?

As the author of a class thinking about how to solve these issues is really important. And this one is solvable. For pure Xojo code and for plugin authors.

Recall that Introspection allows you to look at a class, and its constructors. As well you can invoke one and get back a new instance.

So lets create a mechanism to let the superclass know about subclasses, and then use that knowledge to create the right instances when we need them.

First lets add the “way to know about subclasses”

At runtime the way to “know” about other classes is .. introspection !

And that knowledge is a typeinfo object.

So our superclass needs a way to get the typeinfo’s of subclasses and hang on to it for later use.

Holding on to it for later is easy – an array of Introspection.TypeInfo objects will suffice.

  Dim mSubTypes() as Introspection.TypeInfo

Now how do we get all the info about subtypes ? 

We cant just go through all the objects that exist at runtime because if there are no instances of subtypes yet then we would not find any. So we need some way to “register” the subtypes with the superclass so it can use this information later.

So a method like

  Shared Sub RegisterSubType( subType() as Introspection.TypeInfo)

that adds to the array we defined earlier should suffice

Our class now looks like

Class MySuperClass
  Private Sub Constructor()
  End Sub

 Shared Function CreateNew(name as string)
    select case name
    case “MyCustomSubclass”
       return new MyCustomSubclass
    else
      return new MySuperClass
    end select
  End Function

  Shared Sub RegisterSubType(
         subType as Introspection.TypeInfo)
    mSubtypes.Append subType
  End Sub

  Private Dim mSubTypes() as Introspection.TypeInfo

End Class

And now all we really need to fix is the CreateNew method so it can return a subtype properly

We’ll leave the parameters as is for now – so we create “by name”

This has some implications, like if you make a typo you wont get back the instance you asked for, but we can fix that later.

The first thing I’ll do is slightly alter the method signature so it has a default parameter.

 Shared Function CreateNew(name as string = “”)

And that’s if for changing the method signature

This allows us to do a tiny bit of optimization AND makes writing code a tiny bit easier

So first things first – if NO name is supplied we just return a new instance of the superclass.

  if name = “” then
    return new MySuperClass
  end if

And after this we have to find the right “TypeInfo” and create an instance from that. And should we find no match we should return nil – which can be used as an error check to find any issues.

Each TypeInfo object has a NAME property.

So we an iterate through our list of registered TypeInfo objects, find the one with the right name, and invoke its Constructor.

  For i As Integer = 0 To mSubTypes.Ubound
    
    // find the type info with the right name
    If mSubTypes(i).Name = subtype then
    
    // found it so get a list of its constructors
    Dim cInfo() As Introspection.ConstructorInfo =
                               mSubTypes(i).GetConstructors
    
    // and find the 0 param constructor
    // since out factory does not pass along any params
    For j As Integer = 0 To cInfo.Ubound
      Dim pInfo() As Introspection.ParameterInfo = 
                                 cInfo(j).GetParameters
      
      // has no params ?
      If pInfo.ubound < 0 Then
        // yes - invoke this one & return the result
        // which will be an instance of the right type
        Return cInfo(j).Invoke
      End If
      
    Next
    
  End If
  
  Next

  // if we reach here we will be default return a nil 
  // or we could explicitly return nil

And there we go – a superclass with a factory method that can be extended by anyone – with or without source code !

The end result is a class as follows

Class MySuperClass
  Private Sub Constructor()
  End Sub

  Shared Function CreateNew(name as string = “”)
    if name = “” then
      return new MySuperClass
    end if

   For i As Integer = 0 To mSubTypes.Ubound
    
      // find the type info with the right name
      If mSubTypes(i).Name = subtype then
    
      // found it so get a list of its constructors
      Dim cInfo() As Introspection.ConstructorInfo =
                               mSubTypes(i).GetConstructors
    
      // and find the 0 param constructor
      // since out factory does not pass along any params
      For j As Integer = 0 To cInfo.Ubound
        Dim pInfo() As Introspection.ParameterInfo = 
                                 cInfo(j).GetParameters
      
        // has no params ?
        If pInfo.ubound < 0 Then
          // yes - invoke this one & return the result
          // which will be an instance of the right type
          Return cInfo(j).Invoke
        End If
      
      Next
    
    End If
  
    Next

    // if we reach here we will be default return a nil 
    // or we could explicitly return nil
  End Function

  Shared Sub RegisterSubType(
         subType as Introspection.TypeInfo)
    mSubtypes.Append subType
  End Sub

  Private Dim mSubTypes() as Introspection.TypeInfo

End Class

Something you might do is to make the factory NOT take a string but a typeinfo so that there’s no “typo’s” to debug at runtime. Using a typeinfo would mean most typo issues would be caught at compile time.

That’s left as an exercise for the reader.

Code for safety

Lots of time you see code like

static flag as boolean 
if flag then return

flag = true

// rest of method

flag = false

In a simple method/event with only a handful of lines there’s probably nothing wrong with this

But what do you do when the method spans into hundreds or thousands of lines ?

And if you use the philosophy of “bail early” ?

Then your methods/events start to look like

static flag as boolean 
if flag then return
flag = true

if condition then
  flag = false
  return
end if

if condition2 then
  if condition3 then
    flag = false
    return
  end if
else
    flag = false
    return
end if

flag = false

And following all those returns & making sure you reset the flag correctly in every one is tedious.

So what if you could make it so you NEVER had to worry about the flag remaining set when you returned ?

Remember that objects get destroyed when the last reference to them is removed – they automatically get cleaned up.

At first glance it seems that you should be able to do

static flag as date
if flag <> nil then return
flag = new Date()

// rest of method
return

and then when the method ends the date object would go out of scope, get destroyed and the world would be happy & safe for not forgetting to flip that flag.

Sadly because the variable is a static this wont happen – the static persists across calls and so it wont get destroyed.

So the trick is how to make the variable persist across method calls AND also get destroyed when things go out of scope.

But that doesn’t mean we’re stuck.

One issue we do have is that in the way we’ve set up our flag property its a value type which means other code can’t hold on to a reference to it to do anything later.

And because its a static declared in a method other code outside this method cannot touch it to flip its value.

So we need to deal with both these issues.

The second one is easiest to deal with – we can simply move the static from being declared in the method to a property on the class that is only used by this method (although its much more usual to see such a blocking action like this happen in several methods or events rather than just a single one)

So we’ll change

static flag as date

to a similarly named property on this class / window 

By simply doing this we make it possible to use an object that, when created and then goes out of scope makes it so we can use the constructor & destructor to change out flag so things get blocked & allowed as needed.


So how do we have something flip the flag when we need ?

In theory we want our code to look like

if flag then return // remember flag is a private 
                    // or protected property on the class

dim flipper as new FlagFlipper( ???????? )

// rest of method

So what does this “Flipper” thing looks like & how does it work ?

We’ll create a class – FlagFlipper. 

And this class needs to then be able to know how to set and clear the flag we set up. But we really don’t want this new class to have to reach inside other classes to do this.

And this is where delegates come into play.

A delegate is a “type safe function pointer” which means that

it’s a function you can pass around like any other parameter

 it’s type safe – you can’t just pass any old function 

So our new class is going to look something like

Class FlagFlipper
  Constructor( ?????????? )
    // flip the flag in the target class somehow

  End Constructor

  Destructor()
    // flip the flag in the target class somehow
  End Destructor
End Class

To this we’ll add 2 delegates

Delegate SetFlag()
Delegate ClearFlag()

Note that we do not put code in these.

Recall we do not want the flag flipper to know the innards of a class to know how to do its work.

So we need to “pass” the right “function” to the flipper so it can call them without having to know anything more than the two delegates.

So how do we do that ?

Well … addressof CREATES an instance of a delegate

So that seems like we need to use that somehow

We want the actual management of the flag to be in our original class.

So the methods to set and clear the flag should be part of that class (and it really doesn’t matter if this is a class/layout/ etc) Lets suppose we were originally using a Window – so we’ll add code to the Window

In my example so far things look like

Window Window1

  Event Open
    foo
  End Event

  Method foo
    if flag then return

    dim flipper as new FlagFlipper( ??????????? )

    foo // to make it so we can see the 
        // second call to foo is blocked

  End Method

  Private Property flag as boolan

End Window

And as stated we’re going to add two methods – setflag and clear flag

Now things look like

Window Window1

  Event Open
    foo
  End Event

  Sub foo
    if flag then return

    dim flipper as new FlagFlipper( ??????????? )

    foo // to make it so we can see the 
        // second call to foo is blocked

  End Sub
  
  Private Sub SetFlag()
    flag = true
  End Sub
  Private Sub ClearFlag()
    flag = false
  End Sub

  Private Property flag as boolan

End Window

Now how do we have to make the Constructor & set up of the instance look so the right setflag / clearflag methods are called ?

Well … delegates & address of !

If we make the constructor look like the following 

Class FlagFlipper
  Constructor( setFlagMethod as SetFlag, 
                 clearFlagMethod as ClearFlag )
    // flip the flag in the target class somehow
    setFlagMethod.Invoke
    mSetFlag = setFlagMethod
    mClearFlag = clearFlagMethod 

  End Constructor

  Destructor()
    // flip the flag in the target class somehow

  End Destructor

  Delegate SetFlag()
  Delegate ClearFlag()

  Private mSetFlag as SetFlag
  Private mClearFlag as ClearFlag 

End Class

Note that it holds on to a reference to the method to call to set or clear the flag

And the set up in the method that originally needed the flag looks like

Window Window1

  Event Open
    foo
  End Event

  Sub foo
    if flag then return

    dim flipper as new FlagFlipper( AddressOf SetFlag,
                      AddressOf ClearFlag )

    foo // to make it so we can see the 
        // second call to foo is blocked

  End Sub
  
  Private Sub SetFlag()
    flag = true
  End Sub

  Private Sub ClearFlag()
    flag = false
  End Sub

  Private Property flag as boolan

End Window

And now, by using an object that when it goes out of scope automatically cleans up after itself we’ll no longer have to worry about “did I clear that flag ?”

Here’s the completed project