This one might surprise you

Lets start with the code

Dim v1 As Variant = Nil
Dim v2 As Variant = 12

If v1 < v2 Then
  Break
Elseif v2 < v1 Then
  Break
End If

Which break statement would YOU expect to be hit ? I will say that the one that does get hit here is NOT what I expected at all.

When you compare variants they convert to a common type. Not sure that I know what the common type that would be used is here.

It doesnt appear to be any of the numeric types.

And the comparison doesn’t seem to be relying on the hash value of a variant.

If you add in code to explicitly convert each variant to some other type (Uint64, int64, Object, String, etc) you see that those all have a nil variant being treated as if its 0 and the non-nil variant as if they are the numeric value.

Developers needs are not the same as consumers needs

There are lots of apps; desktop, web, and mobile. And they are for all kinds of needs for general consumption.

Developers needs often don’t fit that model though.

How many developers have IDE’s that the use on the Web ? Or on their mobile phone ? You might be able to write text there but if you using a tool like VS Code, Xcode, etc these are still mostly traditional desktop apps.

And this is where tool vendors often fall down. There are many who say “Hey use our tools you can write macOS, Windows, Linux, mobile, iOS and all kinds of other apps with our tool !” And, as Bob found, this is often like chasing unicorns.

I’ve spent a couple days on the phone with one tool vendor whose answer is “well just use Windows to write your macOS, Linux and Windows apps” To me this makes no sense. If your tool can create applications for macOS isnt the tool written using itself ? And if so then where is the macOS version of the tool since you claim you can write macOS apps. Or the Linux one for the same reason.

There are several tools like this where they claim you can create apps for all sorts of targets BUT you can only use the tool on one of the targets tat are supported. Which tells me that their tool is not written using their tool. If they wont use it to write their tool how can I be sure I can write what I need with their tool ?

While I might be critical of Xojo fairly often ONE thing they do is dog-fooding. They use their tool to create their tool.(1) Bugs in their framework show up in their faces and they have incentive to fix them because otherwise THEY see the bug all the time.

I wish more tool vendors did this.

footnotes

(1) Xojo does a reasonable job of dog-fooding but there are aspects of the framework that are not used in the IDE so they dont dog-food everything as thoroughly as we might like.

Ch-ch-ch-changes

In the world somethings change and some don’t. Some change loudly. Some things change quietly and invisibly.

One that I’m disappointed that has changed kind of quietly is Bob Keeney’s role in the community. Apparently he’s no longer a Xojo consultant.

Its notable that after nearly 20 years as a REALbasic/Xojo consultant Bob has moved into a new role at BlackBag Technologies. Probably not a bad move for him but still a significant change in the community.

Personally I have a pretty good idea what transpired to lead to this change. And while I might be disappointed things culminated in Bob taking a role there I also understand the motivation.

I have no idea if his new role will have him using Xojo or not.

But, the community has lost one of the better examples of building a consultancy using Xojo. Thats disappointing.

I wish him nothing but the best and all the success in the world in his new role.

Is nil or = nil ?

Often in code you might see checks for NIL written as

if foo = nil then

and sometimes you might see

if foo is nil

Whats the difference between the two ?

In Xojo the IS operator compares the references. It doesn’t compare the contents of the objects in any way. It answers the question “do these two references refer to the exact same instance” – in some languages this would be comparing whether two pointers point to the same location.

= will do much the same IF you have NOT implemented operator_compare for your specific classes. However if you HAVE implemented operator_compare then you can get VERY different results as your implementation of operator_compare will be called, even if one of the items is nil. In the following code

if foo = nil then

operator_compare for the instance foo would be called with the rhs parameter as NIL.

You can try this for yourself very quickly.

Create a new desktop project. In that new project add a Class named myClass. Add a method to myClass, Public operator_compare(rhs as myClass) as Integer

Simply put a break statement in the code

Now in Window1.open put

dim foo as new myClass

if foo = nil then // you will hit your break statement in the class
end if

if foo is nil then // you will NOT hit the break statement in the class
end if

The advice here is to be REALLY careful about when you use IS or =, or other comparison operators like >= <= <> etc, as they could mean VERY different things. And without reviewing code you can’t be sure whether a class does or does not have operator_compare implemented.

Use IS when you mean “are these the referring to the same instance”

Use the others when you _may_ mean something else.

Decide by not deciding

I was doing some reading on the weekend and came across some really good thoughts on how to make decisions in code – but not by using conventional if or select branching mechanisms or others that masquerade as flow control statements under other guises.

There’s a whole movement for “if-less programming”.

And it fits very well with using OOP and the capabilities of polymorphism in ways that make your code clearer and easier to maintain and extend.

Let’s say you have a class that represents vehicles. Your program permits you to have many types of vehicles with various capabilities. And somewhere in that class that represents a vehicle you might have code like :

Function calculateMaximumWeightCapacity() as Double
  if ( vehicleType = "Transport" ) then
     // we have to account for the fact this has 18 wheels and 5 axles
  elseif ( vehicleType = "Truck" ) then
     // we have to account for what kind of light duty truck this is
  elseif ( vehicleType = "Car" ) then
     // we have to account for what kind of car this is as a mini cant
     // carry as much as a impala
  end if
End Function

Yes this is contrived but you get the point

IF you have classes that display this kind of code then you probably should consider using polymorphism in a way it can make you life easier.

In your application, if you have this kind of code, then EVERY time you want to add a new kind of vehicle you have code to adjust. You’ll need to update every possible place this kind of selection goes on. And if you miss one you have bugs.

If However we used polymorphism to help us we could be sure that any time we added a new vehicle type we definitely covered all the required functionality AND that we didnt have to adjust a lot of code in many places.(1)

Instead if we had

Class Vehicle
    Private Sub Constructor()
      // this is so we make this class "abstract" and 
      // you cannot create new vehicles - you MUST create 
      // instances of subclasses only
    End Sub

    Function calculateMaximumWeightCapacity() as Double
      // since we have NO way to FORCE a subclass to override this 
      // we put a break in here so we can figure out which subclass 
      // did NOT override this
      BREAK
    End Function
End Class

Class Transport
  Inherits Vehicle
    Function calculateMaximumWeightCapacity() as Double
        // we have to account for the fact this has 18 wheels and 5 axles
        return 30000 // just for fun !
     End Function
End Class

Class Car
  Inherits Vehicle    
End Class

Class Mini
  Inherits Car
    Function calculateMaximumWeightCapacity() as Double
      // we have to account for what kind of car this is as a mini cant
      // carry as much as a impala
      return 500
     End Function
End Class

Class Impala
  Inherits Car
    Function calculateMaximumWeightCapacity() as Double
      // we have to account for what kind of car this is as a mini cant
      // carry as much as a impala
      return 1000
     End Function
End Class

.. and so on ...

And this gets rid of the need to use an IF to test what kind of vehicle it is to determine how to compute the weight. The specific subclass just does it knowing that its a transport, a truck, a mini or an impala.

Function calculateMaximumWeightCapacity() as Double
  return self.calculateMaximumWeightCapacity()
End Function

Note that this code is much simpler to follow.

And when you need to add a new kind of vehicle you add a new class type, recompile and off your program goes because you havent had to hunt around and find all the places where you need to check vehicle types and maybe introduce new bugs.

Polymorphism is definitely your friend here.

footnotes

(1) there are some things that Xojo does NOT provide that would make life simpler. A means of forcing a subclass to override a specific method defined in a super class does NOT exist. IF we use a base class we can only catch that a subclass has not overridden a method. Some languages have a means for a base class to define a method that subclasses MUST implement. Xojo does not.

Its possible to use an interface to force implementors of an interface to implement a method BUT this MAY be the wrong approach for the specific problem.

Is Pro+ worth it ?

I’ve now had use of a Pro+ license for nearly a year.

When this license type was introduced Xojo told us that the Pro+ included

Top Priority Support is just as defined on that page, we’ll bump your support questions to the top of the queue and we’ll review your Feedback cases first. And of course you can set up a call with us anytime too.
Fast Fixes is as defined on that page as well. Because of the difference between bugs and what may be involved in fixing one, we can’t promise that we will fix “X” bugs for you. But we can promise to help you track down an issue in your code, get a bug you’ve discovered fixed more quickly or help you find a workaround.
And yes, we did previously offer a meeting with Geoff but people did not seem to want or use this so we dropped it. Geoff is always interested in hearing from customers, if you want to reach out to him on the forum you can anytime. Or email hello@xojo.com to set up a call.

https://forum.xojo.com/conversation/post/429116

So far my experience is that this is a nice statement but the reality is different. As I write this I still have several cases awaiting review – some for several months

I’ve actually had to ask about getting these reviewed more than once yet there they still sit.

What Top priority support meant wasn’t clear to me what that meant so I sent an email asking

On the page for Pro+, which I now am a holder of (designated), it says Top Priority Support.
We understand that some Xojo users need support issues resolved ASAP. With Xojo Pro Plus, you’ll get support questions answered first and bug reports will be verified first.
Is that for all reports I submit while I hold the license ? Or just ones I specifically bring to your attention ? Thanks

https://forum.xojo.com/conversation/post/429116

And the reply was

Hi Norman,
Pro Plus users cases are automatically flagged in Feedback, so you don’t have to do anything. A case is also flagged if you add your name to it, so you don’t have to be the creator. To be clear, it does not mean we will fix it right away, but it will receive a higher priority. If you encounter anything show-stopping please reach out and bring that to our attention so we can look into it.

I pointed out that I had several cases that had been sitting and I also wrote back saying

I’m not expecting that it will be fixed right away

I just have a number of cases that are still in the Needs Review state and have been for a couple of weeks at least

And got a reply saying

Ok, we’ll take a look.

That was in August and most of these cases have remained in the Needs Review state since then.

In Nov I again asked about the reports still in the Needs Review status and was informed that they would endeavour to get caught up. To date they are not. Some are marked reproducible, some reviewed and some still needs review.

The other thing mentioned in the post is “Fast Fixes” but it was unclear on how many are included with a Pro+ license. So I posed that question and was told

There’s no set number that is listed but 2 per year is what I would work off of.

I haven’t asked to use any of the ones included with the license I’ve been assigned but not having a number stated as part of the license is bothersome to me. Is it more for some customers and fewer for others? Does it depend on the nature of the Fast Fix itself? And what are the criteria for what is and isn’t a Fast Fix?

I certainly can’t answer that. Xojo also wasnt cleear on what might qualify as a Fast fix.

The last item in the list is being able to schedule a call with Geoff. As of today I have an outstanding request to schedule a call with Geoff. So far that has not been scheduled nor have I had any indication that it will be. The email reply I got back made no mention of scheduling a call and focused entirely on other issues unrelated to my request for a call with Geoff.

In my opinion I’m not seeing that holding a Pro+ license actually makes any difference in how fast the reports I file get reviewed or fixed, or that it has any influence on any of the other aspects it claims to have influence over. (1) As of this writing ~60% of my cases are “Open” – either needs review (29 of 396), reproducible (88 of 396), reviewed (92 of 396), or verified (15 of 396).

If I were making a purchasing decision today I would opt for a Pro license. I might get 2 of them if I really needed twice as many installs (Pro+ includes 2x installs). I would save the extra $600. Xojo could alter the Pro+ to permit 3x activations and remove this as a consideration for opting for multiple Pro licenses instead.

Things don’t actually seem to move along any faster because its a Pro+ user reporting it or not.

YMMV. Anyone else have a Pro+/Enterprise license and have anything different to report ?

 

(1) Note this could be simply because I am who I am and Xojo does seem to treat me differently than other customers. I cannot say why they do this. It just seems to occur and others have mentioned they notice this difference to me.

Programming thought experiments

Some companies like to pose certain programming questions as part of their interview process.

I’ve run into a variety of these. They’ve been SQL related questions, code writing, and algorithm descriptions. Some were fairly straight forward. Some less so.

One of the best I heard was a series of “How would you write this code if you had to write it …” with varying restrictions put on things. And the code was pretty simple. Write code to count all the upper and lower case letters in a string of ASCII characters.

First write the code however you wanted. Loops, if then else, select case.

Depending on which branching style you used the first time then the follow on was to write it using the other. If you first used a massive if then elseif statement then switch to using a select case.

And of course take into account that Xojo IS not case sensitive with string comparisons.

And finally to not use a branching type at all. This requires some out of the box thinking. Literally “count all the upper and lower case ASCII letters without the use of IF, SELECT or any other branching control.” All you have to use is a loop (while/wend, for/next whatever you wanted)

This first two bits are fairly straight forward.

The third however is still one of my favourite “thinking out of the box” approaches.

Anyone care to take a guess at how to achieve that one ?

32 bit apps in a 64 bit era

MacOS has been fully 64 bit since the release of 10.7 (Lion) in 2011.

Yet is has continued to support running 32 bit apps up until the release of 10.15 (Catalina) which removes support for 32 bit apps entirely.

There are ways to work around this like running an old version of macOS in a VM.

There are many apps that have not been updated for 64 bit. Things like AccountEdge (what used to be MYOB) wont be updated to be 64 bit. Old versions of MS Office need to be updated to newer ones as they too are 32 bit and will not operate on Catalina.

And anyone producing apps in Xojo should be building ONLY for 64 bit macOS. I’d encourage that even if you have to support old versions of macOS since all versions that Xojo supports are all 64 bit.

If you’re still building for 32 bit macOS you should update now and be building for 64 bit.

I’d encourage you to do the same for Linux as most modern distros are 64 bit.

The only target where you might need to still build a 32 bit and 64 bit version is Windows where you can get both 32 and 64 bit versions. While most machines sold today are 64 bit and installing a 32 bit OS on them doesn’t make much sense there may be legacy machines running a 32 bit version.

MacOS plists

Xojo includes the ability for you to supplement the plist a macOS build creates.

You can’t overwrite the items the IDE will generate for you but you can add things like heys for App Transport security, Crash on Exceptions and even your own custom items if you want them.

The entire of creating and adding a plist is fairly simple.

Start a text editor. Notepad, textEdit, BBEdit or whatever one you happen to use (vi, emacs, nano, etc will all work just as well)

Make sure you create a “proper” plist that includes the normal header and footer. its just an xml file. The basic form is as follows :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
    <!-- your additions go here -->
</dict>
</plist>

Then you do need to look up the specifics of whatever key it is you’re adding and how it should be written.

The really lazy way is to open Xcode and use its built in plist editor by selecting File > New File > macOS > Property List and then saving the file. But for folks on other OSes thats not going to work.

A lot of the keys like Crash On Exceptions are booleans which are written as

<key> THE KEY NAME HERE </key><true/> 

or false instead of true if the item should be off. Others like Apple Event usage are strings as follows

<key>NSAppleEventsUsageDescription</key><string> YOUR DESCRIPTION OF WHY YOU NEED TO USE APPLE EVENTS HERE</string>

There are LOTS of possible keys that can be in a plist. Adding them at build time can make a tedious process a bit simpler.