ByVal and ByRef

A recent thread on the forums made it clear there is some lack of clarity about ByVal and ByRef

So here’s yet another attempt.

Value types are ones that the data assigned to them is stored right IN the memory location the compiler set aside for them.

A statement like

dim i as integer

reserves a spot in memory when you compile. When you later do

i = 100

the value 100 is put in the spot reserved

For a reference type, one that you create using the NEW keyword, what is reserved by the compiler is a spot to hold the “address” of whatever kind of object defined. A statement like

dim d as Date

sets aside a spot to hold the address of a Date. When you later do

d = new Date

what gets put in the spot that was reserved is not the data for a Date object but the “address” of that data – the reference to the data

Final(ly)

Some languages have to notion of FINAL for methods, events, properties and many other aspects of the language.

But what exactly does FINAL do or mean ?

In other languages, like Java, FINAL has other uses like creating “constants” which there is no need for in Xojo. In those languages a FINAL property is a constant.

In some cases though you might create a class and implement a method that you do NOT want subclasses to override. This could be needed for some algorithm where a subclass overriding the method could negatively affect the operation of the algorithm.

A good example might be something like a StringBuilder class that has an internal buffer that it uses to create a fast string building mechanism. The method that manipulates this internal buffer should be an implementation detail that subclasses should probably not be able to override.

Currently in Xojo the only way to make a method NOT overridable is to make it private. But as soon as you do that subclasses cannot call it.

In Xojo if you want this class to be subclassable you have to make its methods either public or protected. And as soon as you do that a subclass CAN override those methods.

Being able to mark a method as FINAL would prevent the ability of a subclass to subvert and take over certain critical function and still make the method usable by the subclass.

On being a developer

As developers we need to be more than just average consumers of technology.

That means we need to be more realistic about things like system updates and patches than just blindly installing them especially on our primary working machine.

At the very least we need to be able to test the very latest. You know our users are going to install the latest betas and run them as soon as possible. And we still need to be able to test on the oldest systems we say we support.

Maybe that means you have a bunch of bootable systems so you can test your software on older versions of MacOS, Windows, Linux or whatever other OSes you support. VM’s _may_ be sufficient for this although if you have hardware dependencies they can be tough to test.

Or, like many Mac developers have experienced, a VM may hide a problem from you. Windows flickering is almost non-existent in some VM’s running on macOS as the VM is double buffered by the underlying host OS. So you never see that issue running in some VM’s on macOS. But testing on real hardware may show it to you.

For me this has typically meant having several removable drives that I can boot from on my Mac. I have everything from 10.10 up to 10.15 bootable. For Window I have Windows 7, 8 and 10 as bootable drives for my PC. For linux I’ll do similar if the need arises.

In many cases a user may “update first and ask questions later”.

As a software developer we need to do better than that.

New Attributes in 2019r2

There’s a lot of things to digest in 2019r2

One of the handy things that was added is a new Attribute you can make use of in your own custom controls – DefaultEvent

By adding this attribute to your custom class’ attributes you can make it so any one of the events your custom controls exposes is the “default event”. This is the one that will be selected when a user puts an instance of your control on a layout and adds events to it.

Handy stuff.

ToHex

Converting numbers, especially ones of a specific size, to hex has long been problematic. The built in functions don’t do a very good job with it and often drop leading zeros even when the integers size is known.


Dim s1 As String 
s1 = Hex(13) // here 13 is an "Integer" literal 
             // and should be treated as a 32 bit integer in a 32 bit build
             // or a 64 bit integer in a 64 bit build

Dim i8 As Int8 = 13
Dim s2 As String
s2 = i8.ToHex

Break

If you look at the values in S1 and S2 produced by the framework functions you’ll see that all leading 0’s are dropped event though the integers are of known size and a proper Hex representation of these should include the leading 0’s. But they don’t.

Most time dropping the leading 0’s is not a big deal. If you are just saving the value into a db, file etc and then eventually converting it back into a value using VAL it wont matter. But when you need it for some other purose then it really does matter. Like when you’re generating a hex key value or something where those leading 0 digits ARE relevant.

So I created a module that does a “proper” hexing of numeric values that does retain the leading 0’s.

Enjoy it

Game of Code

Or “write code like you immediately forget what you wrote” so it’s not a guessing game to figure out why you wrote what you wrote way back when.

What do I mean by that ?

Write code CLEARLY. Use constants liberally and give them good meaningful names.

So instead of writing a line like

If asc(key) = 16 or asc(key) = 204 then

where 16 and 204 are not obvious to everyone maybe write this as

Const ctrlP = 16
Const F5 = 204

if asc(key) = ctrlP  or asc(key) = F5 then

And then even when you go back and look at this code in 6 months even you won’t have to guess what 16 and 204 mean.

Maintaining backwards compatibility in 2019r2

Subclasses, modules and compatibility flags 😛

In Xojo it never used to require a lot of hard work to work across multiple versions. If you simply avoided using the new features then a project could mostly move back and forth between versions without much effort. You could even deal with a lot of newer version changes with a few #If XojoVersion wrappers around bits of code.

2019R2 makes this a little more challenging.

Most of the issues I’ve experienced are because one clients code has a lot of custom control subclasses and these subclasses defined new events. And now, with the takeover of so many event names, these subclass events conflict with the names Xojo took over. It makes it so these client projects no longer just open and compile in 2019r2. They get thousands of compilation errors.

This makes updating to 2019r2 tricky for this client. Especially since they also want to maintain the ability to compile and work in older versions of Xojo to be able to compile for older versions of the OSes they support.

If you’re in the same position there is a way to make it so the event names that were taken over won’t affect client projects.

How ? I created a set of subclass of the built in controls and classes which all client subclasses could be based on and, depending on the build version of Xojo, I could switch these custom subclasses on and off and the rest of the clients subclasses are unaware this has occurred.

What I am not sure of is how far back this technique will work.
Really old versions MAY not interpret compatibility flags quite right.

Now for the HOW TO guide :

  1. In this project I opened it in 2019r2
  2. I created a module called For2019r2
  3. I cleared ALL the compatibility flags for the module so its not compatible with ANY targets
  4. In this module I created new subclasses of every control used and set their scope To “global”
  5. In each subclass I add new event definitions for all the OLD events
  6. In these subclasses I implemented the new event handlers that got renamed to raise the old events added in step 5.

I implemented the “new events” and simply had them raise an event with the old name & params. I could have name these events anything I wanted. By doing this I could add my own methods, properties, etc or even rename any properties Xojo also renamed. I could also handle any exceptions raised and just set error codes or whatever I wanted. I’ve written before about how to do this shadowing “properly”. Thats the technique in use here. What we’re adding this time is the ability to have two different sets of these properly subclassed and shadowed controls that we can switch between.

I saved this project and then in 2019r1.1 I reopened this project as there is some work you cannot do in 2019r2. In the subclasses in the For2019r2 module we also need to add the OLD events which still exist but, because you started the project in2019r2, you can’t see them nor can you add them in 2019r2. We need to also implement the old event handlers and have them raise the event with the old name as well. This is important otherwise in R2 you will get errors about the event definition existing and colliding.

For older IDE’s we create a new module named For2019r1AndEarlier and do much the same adding subclasses of all the controls we need. This time we add just the old event name and a matching event definition for the old event.

The important thing to do is in the module fore 2019r2 if you named the Canvas subclass MySubClass then in the 2019r1 module name the canvas subclass the exact same thing. The same is true for all other control subclasses. They need to be named the same in the For2019r2 and For2019r1AndEarlier modules. This way when you create a new instance on a layout and make its super MySubclass, depending on which module has its compatibility flag enabled you will actually be creating an instance derived from a different superclass.

Now when I want to compile in R2 I select the For2019r2 module & enable the Desktop 32 and 64 bit compatibility flags so my custom subclasses which are outside this module use the base classes inside this module.
When I want to compile using 2019r1.1 and earlier I disable the compat flags on the For2019r2 module and enable the compt flag on the For2019r1AndEarlier so my other classes now use these as their base class.

And you can now ignore R2 event name changes and name these events to whatever you want.

Caveat – i have found a couple interesting bugs in the 2019r1.1 IDE doing this

When moving some control subclasses into a folder insances on a layout may “lose” their super especially if neither of the modules has a compat flag set.
So you get an error like

CustomTextField.Super
Can't find a type with this name. Did you mean class For2019r1andEarlier.MyTextFieldBase?
MyTextFieldBase

Fixing this amounts to enabling one of the compat flags and then going to the super field of the affected control and putting the cursor in the super field and pressing enter

Here’s an example  that shows how I’ve set things up

Xojo 2019r2 & API 2.0

There’s a lot of changes in R2

There are some that are very minor. Like making VAR a synonym for DIM. You can use it or not. It functions no differently.

Some of them are very welcome like updates to URLConnection for one. The JSON Parse and Generate methods seem to work a LOT faster now. And there are a pile of useful extensions on various types. And a lot of fixes in the IDE to make it faster.

The navigator draws a little differently but seems a bit snappier.

Folderitem was updated significantly on macOS to use much more modern API’s. The newer APIs used should make folderitems operate a lot faster on newer versions of macOS. They no longer use the slow code path that Apple had in place that could make APSF volumes really slow with older versions.

A number of things that have been deprecated for a long time are removed so you will have to update code to fix those if you’ve avoided them until now. If you still need to use this code in an older version you can use an #if XojoVersion conditional compilation directive around the old code and it will compile without issue.

That’s the easy stuff.

There are a couple changes that may cause problems as they are silently going to happen just by opening your project in 2019r2.

If you placed TCPSockets, UDPSockets or instances of any of their subclasses on layouts at design time then be aware that the Error event will get a new parameters when you open in 2019r2. This _should_ not have any effect or cause any issues.

If you create folderitems using URL’s check all your inputs to the constructors. I’d strongly recommend you analyze your project and look for deprecated folderitem constructors. If you happened to write code that uses an URL Path with a query portion to get a folder item this behaviour has changed between older versions and 2019r2. The old and new constructors both get this changed behaviour. If you had code that did something like

Dim file As FolderItem = SpecialFolder.Desktop.child("Hello World")
Dim urlpath As String = normFile.URLPath + "?key=value"
Dim resultfile As folderitem = GetFolderItem(urlpath,FolderItem.PathTypeURL)

You’ll find that the result you get in 2019r1.1 and earlier is quite different that what you get in 2019r2. Xojo chose not to fix this behaviour change or introduce a new FileSystemItem class to segregate the old and new behaviour like they did with Date and DateTime. While I understand their issue with updating the entire framework to use this new FileSystemItem or duplicating every function to have old functions returning folderitems and new ones returning FileSystemItems its still disappointing that this reasonably silent behaviour change has happened. I’d be surprised if a lot of people used URL paths this way. I do know its more than zero that did and they’ll have to update their code to deal with this difference.

Another thing that may make updating difficult is that a fairly large number of events and properties got renamed. When you open your project in 2019r2 the renamed events are not automatically updated to their new names so both the old and new event names exist. This may not affect you. The issue I’ve experienced is that if you happened to subclass controls and added events to your subclasses the new names Xojo is using might conflict with the ones you defined previously.

The really hard part is that to fix this you have a hard time doing it 100% accurately in a large projects in 2019r2. Xojo can’t help you because the old event name is still legal to use and instances can implement it. Its just not the event you defined previously in your subclass. Its now the one Xojo defined. If you find you’re in this position make sure you do whatever updating and renaming of your events in 2019r1.1 as the 2019r2 compiler can’t help you find them.

For example if in 2019r1.1 you created the following

Class CustomTextField
Inherits TextField
		Sub TextChange() Handles Event
		  
		End Sub

		EventDef TextChanged()
End Class

and then put an instance of this class on a window layout and Run everything is fine. Save this project and reopen it in 2019R2. You should get a compile error

CustomTextField.TextChanged Declaration
 This property has the same name as an event. You must resolve this conflict
 Event TextChanged()

Xojo added a new TextChanged event to TextField. And now the event definition you had in your subclass now conflicts with the Xojo one. If you alter your TextChanged event definition to be DoTextChanged and run everything seem to work. Your project compiles and runs but TextChanged in the instance on the layout is NOT going to be the DoTextChanged event that you defined before. Nor will it get raised when you expect.

Now the TextChanged event is the implementation of the framework event because the name was taken over. And, since R2 takes this name over, you have a hard time being 100% sure you have fixed all your implementations and all the code that raised that event. It all still compiles without error. So if you have this situation fix these errors in 2019r1.1 which WILL complain if you miss one or don’t fix the code that raises your custom event.

So what CAN you do about this if you do not want to do a LOT of work right now but want to get the fixes for other items ?

That will have to be a whole new column on dealing with the differences as it definitely depends on your circumstances and whether you need to support backwards compatibility with oder versions of Xojo.

R2 deprecates a LOT of methods. Things like Mid have been renamed to Middle. The renaming is fairly innocuous. However an analyze of one of my clients projects resulted in more than 15000 deprecation warnings. Theres just no easy way to deal with that many.

Be careful about just updating with the suggested replacement without examining your code. The reason is that in many cases the old method might have used 1 based indexes and the new one uses 0 based indexes. So you not only have to replace the name you also have to examine the code to adjust for the different indexing or you will cause a lot of off by one errors.

And, as soon as you do update to use the new methods, you are going to need to handle exceptions they may raise. API 2.0 is switching everything to using exceptions rather than error codes. We’ll have to see what the net effect of this is but exceptions are slower than error codes when you have to deal with a lot of them.

There are pros and cons to this approach. Runtime errors of any kind can’t be “ignored” by failing to check an error code. You can ignore the exceptions but then your application will just crash or quit with an unhandled exception. Now you MUST write code to deliberately catch, and maybe ignore, whatever exceptions that get raised. Hopefully these all get well documented so you dont just use

Try
   // some new API 2.0 code
Catch exc as RuntimeException
End Try

I’d advice against a “catch all errors” kind of usage. You should never catch more than the errors you CAN actually deal with and let the rest bubble on up.

2019r2 is, for me, a mixed bag. Some welcome stuff. Some serious pain points. And some stuff that I have to just not use if I want to make code that still compiles in older IDE’s (which for some clients has to). There are things to like in 2019r2, and things that are going to make for a LOT of rework. For me there just arent enough nice things to warrant moving to it for my day in day out work at this time.

Your mileage may vary.

Sort like Finder

Sometimes you want to be able to sort things in the same fashion as the Finder. This method when used as the comparison function for the Arry.Sort( delegate) form of sorting will do that

Public Function CompareLikeFinder(firstString as string, secondString as String) as integer
  #If targetMacOS
    // // 
    // // typedef NS_CLOSED_ENUM(NSInteger, NSComparisonResult) {
    // // NSOrderedAscending = -1L,
    // // NSOrderedSame,
    // // NSOrderedDescending
    // // };
    // 
    // // this gives us "Finder like" comparisons
    
    // -[NSString localizedStandardCompare:].
    Declare Function localizedStandardCompare Lib "Foundation" selector "localizedStandardCompare:" (string1 As CFStringRef, string2 As CFStringRef) As Integer
    Return localizedStandardCompare(firstString, secondString)
    
    
  #Else
    
    Return StrComp(firstString, secondString, REALbasic.StrCompLexical)
    
  #EndIf
  
  
  
End Function

So with code like

Dim strings() As String
strings.append "file10"
strings.append "file1"
strings.append "file2"
strings.append "file11"

Strings.sort( AddressOf CompareLikeFinder )

You will get

file1
file2
file10
file11

instead of a strictly lexically ordered list